# SPDX-License-Identifier: AGPL-3.0-only # Copyright (c) 2026 sol pbc from __future__ import annotations import hashlib import json from importlib import import_module from io import BytesIO from pathlib import Path import pytest from flask import Blueprint, Flask import solstone.convey.state as convey_state journal_sources = import_module("solstone.apps.import.journal_sources") ingest = import_module("solstone.apps.import.ingest") create_state_directory = journal_sources.create_state_directory generate_key = journal_sources.generate_key get_state_directory = journal_sources.get_state_directory load_journal_source = journal_sources.load_journal_source save_journal_source = journal_sources.save_journal_source register_ingest_routes = ingest.register_ingest_routes @pytest.fixture def journal_env(tmp_path, monkeypatch): monkeypatch.setattr(convey_state, "journal_root", str(tmp_path), raising=False) monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) (tmp_path / "apps" / "import" / "journal_sources").mkdir( parents=True, exist_ok=True ) return tmp_path def _source(name="test-source", key=None, **overrides): if key is None: key = generate_key() source = { "name": name, "key": key, "created_at": 1000, "enabled": True, "revoked": False, "revoked_at": None, "stats": { "segments_received": 0, "entities_received": 0, "facets_received": 0, "imports_received": 0, "config_received": 0, }, } source.update(overrides) return source @pytest.fixture def ingest_env(journal_env): key = generate_key() source = _source(key=key) save_journal_source(source) key_prefix = key[:8] create_state_directory(journal_env, key_prefix) entity_state = { "id_map": { "source_entity": "target_entity", "same_entity": "same_entity", }, "received": {}, } (get_state_directory(key_prefix) / "entities" / "state.json").write_text( json.dumps(entity_state, indent=2), encoding="utf-8" ) app = Flask(__name__) app.config["TESTING"] = True bp = Blueprint("import-test", __name__, url_prefix="/app/import") register_ingest_routes(bp) app.register_blueprint(bp) return { "root": journal_env, "key": key, "key_prefix": key_prefix, "source": source, "client": app.test_client(), } def _post_facets(client, key, key_prefix, facets_metadata, file_map): data = {"metadata": json.dumps({"facets": facets_metadata})} data.update(file_map) return client.post( f"/app/import/journal/{key_prefix}/ingest/facets", headers={"Authorization": f"Bearer {key}"}, data=data, content_type="multipart/form-data", ) def _build_request(facets): facets_metadata = [] file_map = {} for facet_idx, facet in enumerate(facets): facet_meta = {"name": facet["name"], "files": []} for file_idx, file_info in enumerate(facet["files"]): facet_meta["files"].append( {"path": file_info["path"], "type": file_info["type"]} ) filename = Path(file_info["path"]).name file_map[f"files_{facet_idx}_{file_idx}"] = ( BytesIO(file_info["content"]), filename, ) facets_metadata.append(facet_meta) return facets_metadata, file_map def _read_state(key_prefix: str) -> dict: state_path = get_state_directory(key_prefix) / "facets" / "state.json" return json.loads(state_path.read_text(encoding="utf-8")) def _read_log(key_prefix: str) -> list[dict]: log_path = get_state_directory(key_prefix) / "facets" / "log.jsonl" if not log_path.exists(): return [] return [ json.loads(line) for line in log_path.read_text(encoding="utf-8").splitlines() if line.strip() ] def _read_staged( key_prefix: str, facet: str, file_type: str, relative_path: str ) -> dict: staged_name = relative_path.replace("/", "__") + ".staged.json" staged_path = ( get_state_directory(key_prefix) / "facets" / "staged" / facet / file_type / staged_name ) return json.loads(staged_path.read_text(encoding="utf-8")) def _json_bytes(data: dict) -> bytes: return (json.dumps(data, ensure_ascii=False, indent=2) + "\n").encode("utf-8") def _jsonl_bytes(items: list[dict]) -> bytes: return "".join( json.dumps(item, ensure_ascii=False) + "\n" for item in items ).encode("utf-8") def _read_json(path: Path) -> dict: return json.loads(path.read_text(encoding="utf-8")) def _read_jsonl_file(path: Path) -> list[dict]: if not path.exists(): return [] return [ json.loads(line) for line in path.read_text(encoding="utf-8").splitlines() if line.strip() ] def _hash_bytes(content: bytes) -> str: return hashlib.sha256(content).hexdigest() def _write_json(path: Path, data: dict) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text( json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8", ) def _write_jsonl(path: Path, items: list[dict]) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(_jsonl_bytes(items).decode("utf-8"), encoding="utf-8") def test_auth_missing(ingest_env): env = ingest_env response = env["client"].post( f"/app/import/journal/{env['key_prefix']}/ingest/facets", data={"metadata": json.dumps({"facets": []})}, content_type="multipart/form-data", ) assert response.status_code == 401 def test_auth_invalid(ingest_env): env = ingest_env response = env["client"].post( f"/app/import/journal/{env['key_prefix']}/ingest/facets", headers={"Authorization": "Bearer wrong-token"}, data={"metadata": json.dumps({"facets": []})}, content_type="multipart/form-data", ) assert response.status_code == 401 def test_auth_revoked(ingest_env): env = ingest_env env["source"]["revoked"] = True env["source"]["revoked_at"] = 12345 save_journal_source(env["source"]) response = env["client"].post( f"/app/import/journal/{env['key_prefix']}/ingest/facets", headers={"Authorization": f"Bearer {env['key']}"}, data={"metadata": json.dumps({"facets": []})}, content_type="multipart/form-data", ) assert response.status_code == 403 def test_key_prefix_mismatch(ingest_env): env = ingest_env response = env["client"].post( "/app/import/journal/deadbeef/ingest/facets", headers={"Authorization": f"Bearer {env['key']}"}, data={"metadata": json.dumps({"facets": []})}, content_type="multipart/form-data", ) assert response.status_code == 403 def test_missing_metadata(ingest_env): env = ingest_env response = env["client"].post( f"/app/import/journal/{env['key_prefix']}/ingest/facets", headers={"Authorization": f"Bearer {env['key']}"}, content_type="multipart/form-data", ) assert response.status_code == 400 payload = response.get_json() assert payload["error"] == "I couldn't find a required field." assert payload["reason_code"] == "missing_required_field" assert payload["detail"] == "Missing metadata" def test_invalid_metadata_json(ingest_env): env = ingest_env response = env["client"].post( f"/app/import/journal/{env['key_prefix']}/ingest/facets", headers={"Authorization": f"Bearer {env['key']}"}, data={"metadata": "not-json"}, content_type="multipart/form-data", ) assert response.status_code == 400 payload = response.get_json() assert payload["error"] == "I couldn't read that JSON request." assert payload["reason_code"] == "invalid_json_request" assert payload["detail"] == "Invalid metadata JSON" def test_unsafe_facet_name(ingest_env): env = ingest_env for bad_name in ["../etc", "foo/bar", ".", "..", "FOO"]: facets = [ { "name": bad_name, "files": [ { "path": "news/20260305.md", "type": "news", "content": b"x", } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 400, f"Expected 400 for facet name: {bad_name}" payload = response.get_json() assert payload["error"] == "I couldn't use one of those values." assert payload["reason_code"] == "invalid_request_value" assert payload["detail"] == "Invalid facet name" def test_new_facet_without_facet_json_writes_default_metadata(ingest_env): env = ingest_env facets = [ { "name": "fieldwork", "files": [ { "path": "todos/20260305.jsonl", "type": "todos", "content": _jsonl_bytes( [{"text": "Prepare kit", "created_at": 10}] ), }, { "path": "news/20260305.md", "type": "news", "content": b"# Field notes\n", }, ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json() == { "created": 2, "merged": 0, "skipped": 0, "staged": 0, "errors": [], } facet_json = env["root"] / "facets" / "fieldwork" / "facet.json" expected_metadata = { "title": "Fieldwork", "description": "", "color": "#667eea", "emoji": "📦", } assert _read_json(facet_json) == expected_metadata from solstone.think.facets import get_facets facets_listing = get_facets() assert "fieldwork" in facets_listing assert list(facets_listing).count("fieldwork") == 1 metadata, file_map = _build_request(facets) second = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert second.status_code == 200 assert second.get_json() == { "created": 0, "merged": 0, "skipped": 2, "staged": 0, "errors": [], } assert _read_json(facet_json) == expected_metadata facets_listing = get_facets() assert "fieldwork" in facets_listing assert list(facets_listing).count("fieldwork") == 1 def test_new_facet_all_types(ingest_env): env = ingest_env facets = [ { "name": "personal", "files": [ { "path": "facet.json", "type": "facet_json", "content": _json_bytes({"title": "Personal"}), }, { "path": "entities/same_entity/entity.json", "type": "entity_relationship", "content": _json_bytes( {"description": "Close contact", "attached_at": 100} ), }, { "path": "entities/same_entity/observations.jsonl", "type": "entity_observations", "content": _jsonl_bytes( [{"content": "Likes tea", "observed_at": 1}] ), }, { "path": "entities/20260305.jsonl", "type": "detected_entities", "content": _jsonl_bytes( [{"id": "same_entity", "name": "Same Entity", "type": "Person"}] ), }, { "path": "activities/activities.jsonl", "type": "activity_config", "content": _jsonl_bytes( [{"id": "coding", "name": "Coding", "priority": "high"}] ), }, { "path": "activities/20260305.jsonl", "type": "activity_records", "content": _jsonl_bytes( [ { "id": "coding_093000_300", "activity": "coding", "active_entities": ["same_entity"], } ] ), }, { "path": "activities/20260305/coding_093000_300/session_review.md", "type": "activity_output", "content": b"# Session\n", }, { "path": "todos/20260305.jsonl", "type": "todos", "content": _jsonl_bytes([{"text": "Ship it", "created_at": 10}]), }, { "path": "news/20260305.md", "type": "news", "content": b"# News\n", }, { "path": "logs/20260305.jsonl", "type": "logs", "content": _jsonl_bytes([{"event": "ingested"}]), }, ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json() == { "created": 10, "merged": 0, "skipped": 0, "staged": 0, "errors": [], } facet_root = env["root"] / "facets" / "personal" assert _read_json(facet_root / "facet.json") == {"title": "Personal"} assert _read_json(facet_root / "entities" / "same_entity" / "entity.json") == { "description": "Close contact", "attached_at": 100, "entity_id": "same_entity", } assert _read_jsonl_file( facet_root / "entities" / "same_entity" / "observations.jsonl" ) == [{"content": "Likes tea", "observed_at": 1}] assert ( _read_jsonl_file(facet_root / "entities" / "20260305.jsonl")[0]["id"] == "same_entity" ) assert ( _read_jsonl_file(facet_root / "activities" / "activities.jsonl")[0]["id"] == "coding" ) assert ( _read_jsonl_file(facet_root / "activities" / "20260305.jsonl")[0]["id"] == "coding_093000_300" ) assert ( facet_root / "activities" / "20260305" / "coding_093000_300" / "session_review.md" ).read_text(encoding="utf-8") == "# Session\n" assert ( _read_jsonl_file(facet_root / "todos" / "20260305.jsonl")[0]["text"] == "Ship it" ) assert (facet_root / "news" / "20260305.md").read_text( encoding="utf-8" ) == "# News\n" assert ( _read_jsonl_file(facet_root / "logs" / "20260305.jsonl")[0]["event"] == "ingested" ) source = load_journal_source(env["key"]) assert source["stats"]["facets_received"] == 1 def test_existing_facet_merge_entity_relationship(ingest_env): env = ingest_env target_path = ( env["root"] / "facets" / "work" / "entities" / "same_entity" / "entity.json" ) _write_json( target_path, {"entity_id": "same_entity", "description": "Keep target", "attached_at": 200}, ) facets = [ { "name": "work", "files": [ { "path": "entities/same_entity/entity.json", "type": "entity_relationship", "content": _json_bytes( {"description": "Source desc", "last_seen": 999} ), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 assert _read_json(target_path) == { "description": "Keep target", "last_seen": 999, "attached_at": 200, "entity_id": "same_entity", } def test_existing_facet_merge_observations(ingest_env): env = ingest_env target_path = ( env["root"] / "facets" / "work" / "entities" / "same_entity" / "observations.jsonl" ) _write_jsonl( target_path, [ {"content": "Likes tea", "observed_at": 1}, {"content": "Prefers email", "observed_at": 2}, ], ) facets = [ { "name": "work", "files": [ { "path": "entities/same_entity/observations.jsonl", "type": "entity_observations", "content": _jsonl_bytes( [ {"content": "Likes tea", "observed_at": 1}, {"content": "Uses vim", "observed_at": 3}, ] ), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 assert _read_jsonl_file(target_path) == [ {"content": "Likes tea", "observed_at": 1}, {"content": "Prefers email", "observed_at": 2}, {"content": "Uses vim", "observed_at": 3}, ] def test_existing_facet_merge_detected_entities(ingest_env): env = ingest_env target_path = env["root"] / "facets" / "work" / "entities" / "20260305.jsonl" _write_jsonl(target_path, [{"id": "same_entity", "name": "Same", "type": "Person"}]) facets = [ { "name": "work", "files": [ { "path": "entities/20260305.jsonl", "type": "detected_entities", "content": _jsonl_bytes( [ {"id": "same_entity", "name": "Same", "type": "Person"}, {"id": "source_entity", "name": "Source", "type": "Person"}, ] ), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 items = _read_jsonl_file(target_path) assert [item["id"] for item in items] == ["same_entity", "target_entity"] def test_existing_facet_merge_activity_config(ingest_env): env = ingest_env target_path = env["root"] / "facets" / "work" / "activities" / "activities.jsonl" _write_jsonl(target_path, [{"id": "coding", "name": "Coding"}]) facets = [ { "name": "work", "files": [ { "path": "activities/activities.jsonl", "type": "activity_config", "content": _jsonl_bytes( [ {"id": "coding", "name": "Coding"}, {"id": "meeting", "name": "Meeting"}, ] ), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 assert [item["id"] for item in _read_jsonl_file(target_path)] == [ "coding", "meeting", ] def test_existing_facet_merge_activity_records(ingest_env): env = ingest_env target_path = env["root"] / "facets" / "work" / "activities" / "20260305.jsonl" _write_jsonl( target_path, [{"id": "coding_1", "activity": "coding", "active_entities": ["same_entity"]}], ) facets = [ { "name": "work", "files": [ { "path": "activities/20260305.jsonl", "type": "activity_records", "content": _jsonl_bytes( [ { "id": "coding_1", "activity": "coding", "active_entities": ["same_entity"], }, { "id": "coding_2", "activity": "coding", "active_entities": ["source_entity"], }, ] ), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 items = _read_jsonl_file(target_path) assert [item["id"] for item in items] == ["coding_1", "coding_2"] assert items[1]["active_entities"] == ["target_entity"] def test_existing_facet_merge_activity_output_skip(ingest_env): env = ingest_env target_file = ( env["root"] / "facets" / "work" / "activities" / "20260305" / "coding_093000_300" / "session_review.md" ) target_file.parent.mkdir(parents=True, exist_ok=True) target_file.write_text("existing\n", encoding="utf-8") facets = [ { "name": "work", "files": [ { "path": "activities/20260305/coding_093000_300/session_review.md", "type": "activity_output", "content": b"new\n", } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["skipped"] == 1 assert target_file.read_text(encoding="utf-8") == "existing\n" def test_existing_facet_merge_activity_output_copy(ingest_env): env = ingest_env (env["root"] / "facets" / "work").mkdir(parents=True, exist_ok=True) facets = [ { "name": "work", "files": [ { "path": "activities/20260305/coding_093000_300/session_review.md", "type": "activity_output", "content": b"copied\n", } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) target_file = ( env["root"] / "facets" / "work" / "activities" / "20260305" / "coding_093000_300" / "session_review.md" ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 assert target_file.read_text(encoding="utf-8") == "copied\n" def test_existing_facet_merge_todos(ingest_env): env = ingest_env target_path = env["root"] / "facets" / "work" / "todos" / "20260305.jsonl" _write_jsonl(target_path, [{"text": "Ship it", "created_at": 1}]) facets = [ { "name": "work", "files": [ { "path": "todos/20260305.jsonl", "type": "todos", "content": _jsonl_bytes( [ {"text": "Ship it", "created_at": 1}, {"text": "Review PR", "created_at": 2}, ] ), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 assert _read_jsonl_file(target_path) == [ {"text": "Ship it", "created_at": 1}, {"text": "Review PR", "created_at": 2}, ] def test_existing_facet_merge_news_skip(ingest_env): env = ingest_env target_path = env["root"] / "facets" / "work" / "news" / "20260305.md" target_path.parent.mkdir(parents=True, exist_ok=True) target_path.write_text("existing\n", encoding="utf-8") facets = [ { "name": "work", "files": [ { "path": "news/20260305.md", "type": "news", "content": b"new\n", } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["skipped"] == 1 assert target_path.read_text(encoding="utf-8") == "existing\n" def test_existing_facet_merge_news_copy(ingest_env): env = ingest_env (env["root"] / "facets" / "work").mkdir(parents=True, exist_ok=True) facets = [ { "name": "work", "files": [ { "path": "news/20260305.md", "type": "news", "content": b"headline\n", } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) target_path = env["root"] / "facets" / "work" / "news" / "20260305.md" assert response.status_code == 200 assert response.get_json()["merged"] == 1 assert target_path.read_text(encoding="utf-8") == "headline\n" def test_existing_facet_merge_logs(ingest_env): env = ingest_env target_path = env["root"] / "facets" / "work" / "logs" / "20260305.jsonl" _write_jsonl(target_path, [{"event": "existing"}]) facets = [ { "name": "work", "files": [ { "path": "logs/20260305.jsonl", "type": "logs", "content": _jsonl_bytes([{"event": "new"}]), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["merged"] == 1 assert _read_jsonl_file(target_path) == [{"event": "existing"}, {"event": "new"}] def test_entity_id_remapping(ingest_env): env = ingest_env facets = [ { "name": "work", "files": [ { "path": "entities/source_entity/entity.json", "type": "entity_relationship", "content": _json_bytes({"description": "Remapped"}), }, { "path": "entities/source_entity/observations.jsonl", "type": "entity_observations", "content": _jsonl_bytes( [{"content": "Knows Rust", "observed_at": 1}] ), }, { "path": "entities/20260305.jsonl", "type": "detected_entities", "content": _jsonl_bytes( [ { "id": "source_entity", "name": "Source Entity", "type": "Person", } ] ), }, { "path": "activities/20260305.jsonl", "type": "activity_records", "content": _jsonl_bytes( [ { "id": "coding_1", "activity": "coding", "active_entities": ["source_entity"], } ] ), }, ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) facet_root = env["root"] / "facets" / "work" assert response.status_code == 200 assert response.get_json()["created"] == 4 assert (facet_root / "entities" / "target_entity" / "entity.json").exists() assert (facet_root / "entities" / "target_entity" / "observations.jsonl").exists() assert not (facet_root / "entities" / "source_entity").exists() assert ( _read_jsonl_file(facet_root / "entities" / "20260305.jsonl")[0]["id"] == "target_entity" ) assert _read_jsonl_file(facet_root / "activities" / "20260305.jsonl")[0][ "active_entities" ] == ["target_entity"] def test_unmapped_entity_staging(ingest_env): env = ingest_env content = _json_bytes({"description": "Unknown"}) facets = [ { "name": "work", "files": [ { "path": "entities/unknown/entity.json", "type": "entity_relationship", "content": content, } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json() == { "created": 0, "merged": 0, "skipped": 0, "staged": 1, "errors": [], } staged = _read_staged( env["key_prefix"], "work", "entity_relationship", "entities/unknown/entity.json" ) assert staged["reason"] == "unmapped_entity" assert staged["source_entity_id"] == "unknown" assert staged["source_path"] == "entities/unknown/entity.json" assert "unknown" in staged["explanation"] def test_staged_then_retry(ingest_env): env = ingest_env facets = [ { "name": "work", "files": [ { "path": "entities/unknown/entity.json", "type": "entity_relationship", "content": _json_bytes({"description": "test"}), } ], } ] metadata, file_map = _build_request(facets) first = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert first.status_code == 200 assert first.get_json()["staged"] == 1 state_path = get_state_directory(env["key_prefix"]) / "entities" / "state.json" entity_state = json.loads(state_path.read_text(encoding="utf-8")) entity_state["id_map"]["unknown"] = "unknown" state_path.write_text(json.dumps(entity_state), encoding="utf-8") metadata, file_map = _build_request(facets) second = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert second.status_code == 200 body = second.get_json() assert body["staged"] == 0 assert body["skipped"] == 1 assert body["created"] == 0 assert body["merged"] == 0 def test_facet_json_conflict_staging(ingest_env): env = ingest_env target_path = env["root"] / "facets" / "work" / "facet.json" _write_json(target_path, {"title": "Current"}) facets = [ { "name": "work", "files": [ { "path": "facet.json", "type": "facet_json", "content": _json_bytes({"title": "Incoming"}), } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert response.get_json()["staged"] == 1 staged = _read_staged(env["key_prefix"], "work", "facet_json", "facet.json") assert staged["reason"] == "facet_json_conflict" assert staged["source_content"] == {"title": "Incoming"} assert staged["target_content"] == {"title": "Current"} def test_idempotent(ingest_env): env = ingest_env facets = [ { "name": "work", "files": [ {"path": "news/20260305.md", "type": "news", "content": b"repeat\n"} ], } ] metadata, file_map = _build_request(facets) first = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) metadata, file_map = _build_request(facets) second = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert first.status_code == 200 assert second.status_code == 200 assert first.get_json()["created"] == 1 assert second.get_json() == { "created": 0, "merged": 0, "skipped": 1, "staged": 0, "errors": [], } def test_error_isolation(ingest_env): env = ingest_env (env["root"] / "facets" / "work").mkdir(parents=True, exist_ok=True) facets = [ { "name": "work", "files": [ { "path": "entities/20260305.jsonl", "type": "detected_entities", "content": b"{bad json\n", }, {"path": "news/20260305.md", "type": "news", "content": b"good\n"}, ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 body = response.get_json() assert body["merged"] == 1 assert len(body["errors"]) == 1 assert (env["root"] / "facets" / "work" / "news" / "20260305.md").exists() def test_error_isolation_across_facets(ingest_env): env = ingest_env facets = [ { "name": "broken", "files": [ { "path": "activities/activities.jsonl", "type": "activity_config", "content": b"{bad json\n", } ], }, { "name": "good", "files": [{"path": "news/20260305.md", "type": "news", "content": b"ok\n"}], }, ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 body = response.get_json() assert body["created"] == 1 assert len(body["errors"]) == 1 assert (env["root"] / "facets" / "good" / "news" / "20260305.md").exists() def test_stats_update(ingest_env): env = ingest_env facets = [ { "name": "alpha", "files": [ {"path": "news/20260305.md", "type": "news", "content": b"alpha\n"}, { "path": "logs/20260305.jsonl", "type": "logs", "content": _jsonl_bytes([{"event": "alpha"}]), }, ], }, { "name": "beta", "files": [ {"path": "news/20260305.md", "type": "news", "content": b"beta\n"} ], }, { "name": "gamma", "files": [ { "path": "entities/unknown/entity.json", "type": "entity_relationship", "content": _json_bytes({"description": "unknown"}), } ], }, ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) source = load_journal_source(env["key"]) assert response.status_code == 200 assert source["stats"]["facets_received"] == 2 def test_state_manifest(ingest_env): env = ingest_env news = b"news\n" logs = _jsonl_bytes([{"event": "log"}]) facets = [ { "name": "work", "files": [ {"path": "news/20260305.md", "type": "news", "content": news}, {"path": "logs/20260305.jsonl", "type": "logs", "content": logs}, ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert _read_state(env["key_prefix"]) == { "received": { "work/news/20260305.md": _hash_bytes(news), "work/logs/20260305.jsonl": _hash_bytes(logs), } } def test_decision_log(ingest_env): env = ingest_env facets = [ { "name": "work", "files": [ {"path": "news/20260305.md", "type": "news", "content": b"headline\n"} ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 entries = _read_log(env["key_prefix"]) assert len(entries) == 1 entry = entries[0] assert "ts" in entry assert entry["action"] == "facet_file_created" assert entry["item_type"] == "news" assert entry["item_id"] == "work/news/20260305.md" assert entry["facet"] == "work" assert entry["reason"] == "new_facet" def test_error_logged_to_decision_log(ingest_env): env = ingest_env facets = [ { "name": "work", "files": [ { "path": "todos/20260305.jsonl", "type": "todos", "content": b"{bad\n", } ], } ] metadata, file_map = _build_request(facets) response = _post_facets( env["client"], env["key"], env["key_prefix"], metadata, file_map ) assert response.status_code == 200 assert len(response.get_json()["errors"]) == 1 entries = _read_log(env["key_prefix"]) assert len(entries) == 1 assert entries[0]["action"] == "facet_file_error" assert entries[0]["facet"] == "work"