# SPDX-License-Identifier: AGPL-3.0-only # Copyright (c) 2026 sol pbc from __future__ import annotations import json import logging import re import stat from importlib import import_module import pytest from flask import Flask, g, jsonify, request import solstone.convey.state as convey_state from solstone.convey.reasons import INVALID_REQUEST_VALUE from solstone.convey.secure_listener import ConveyIdentity from solstone.convey.utils import error_response from solstone.think.utils import now_ms journal_sources = import_module("solstone.apps.import.journal_sources") STATE_AREAS = journal_sources.STATE_AREAS create_state_directory = journal_sources.create_state_directory find_journal_source_by_name = journal_sources.find_journal_source_by_name generate_key = journal_sources.generate_key get_state_directory = journal_sources.get_state_directory IngestIdentityCase = journal_sources.IngestIdentityCase IngestIdentityError = journal_sources.IngestIdentityError is_valid_journal_source_name = journal_sources.is_valid_journal_source_name journal_source_state_prefix = journal_sources.journal_source_state_prefix list_journal_sources = journal_sources.list_journal_sources load_journal_source = journal_sources.load_journal_source load_journal_source_by_fingerprint = journal_sources.load_journal_source_by_fingerprint mint_pl_journal_source_record = journal_sources.mint_pl_journal_source_record require_journal_source = journal_sources.require_journal_source require_ingest_identity = journal_sources.require_ingest_identity save_journal_source = journal_sources.save_journal_source FINGERPRINT = "sha256:" + "a" * 64 FINGERPRINT_2 = "sha256:" + "b" * 64 @pytest.fixture def journal_env(tmp_path, monkeypatch): monkeypatch.setattr(convey_state, "journal_root", str(tmp_path), raising=False) (tmp_path / "apps" / "import" / "journal_sources").mkdir( parents=True, exist_ok=True ) return tmp_path def _source(name: str, key: str, created_at: int = 0) -> dict: return { "key": key, "name": name, "created_at": created_at, "enabled": True, "revoked": False, "revoked_at": None, "stats": { "segments_received": 0, "entities_received": 0, "facets_received": 0, "imports_received": 0, "config_received": 0, }, } def _pl_source( fingerprint: str = FINGERPRINT, *, device_label: str = "peer laptop", created_at: int = 0, **overrides, ) -> dict: source = { "pair_mode": "pl", "fingerprint": fingerprint, "device_label": device_label, "paired_at": "2026-05-20T00:00:00Z", "created_at": created_at, "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 def _pl_identity(fingerprint: str = FINGERPRINT) -> ConveyIdentity: return ConveyIdentity( mode="pl-direct", fingerprint=fingerprint, device_label="peer laptop", paired_at="2026-05-20T00:00:00Z", session_id="session-1", ) def _auth_app() -> Flask: app = Flask(__name__) @app.before_request def stamp_identity(): stamped = request.environ.get("pl.identity") if stamped is not None: g.identity = stamped @app.route("/protected") @require_journal_source def protected(): return jsonify( { "name": g.journal_source.get("name"), "device_label": g.journal_source.get("device_label"), "pair_mode": g.journal_source.get("pair_mode"), } ) return app @pytest.fixture def manifest_env(journal_env): """Journal env with a saved source and state directory.""" key = generate_key() source = _source("manifest-test", key, created_at=123) save_journal_source(source) create_state_directory(journal_env, key[:8]) return {"root": journal_env, "key": key, "source": source} @pytest.fixture def manifest_app(manifest_env): app = Flask(__name__) @app.before_request def stamp_identity(): stamped = request.environ.get("pl.identity") if stamped is not None: g.identity = stamped @app.route("/journal//manifest/") @require_journal_source def journal_source_manifest(key_prefix: str, area: str): if area not in STATE_AREAS: return error_response( INVALID_REQUEST_VALUE, status=404, detail="Unknown manifest area" ) state_path = get_state_directory(g.derived_prefix) / area / "state.json" try: data = json.loads(state_path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): data = {} return jsonify(data) return app def test_generate_key(): key = generate_key() assert len(key) == 43 assert re.fullmatch(r"[A-Za-z0-9_-]{43}", key) def _assert_ingest_identity_case( app: Flask, expected: IngestIdentityCase, *, headers: dict[str, str] | None = None, identity: ConveyIdentity | None = None, key_prefix: str | None = None, ) -> None: with app.test_request_context(headers=headers or {}): if identity is not None: g.identity = identity with pytest.raises(IngestIdentityError) as exc_info: require_ingest_identity(key_prefix) assert exc_info.value.case is expected def test_require_ingest_identity_valid_dl_bearer(journal_env): key = generate_key() source = _source("identity-dl", key, created_at=123) assert save_journal_source(source) is True app = Flask(__name__) with app.test_request_context(headers={"Authorization": f"Bearer {key}"}): resolved, derived_prefix = require_ingest_identity(key[:8]) assert resolved["name"] == "identity-dl" assert derived_prefix == key[:8] assert derived_prefix == journal_source_state_prefix(resolved) def test_require_ingest_identity_valid_pl(journal_env): source = _pl_source() assert save_journal_source(source) is True app = Flask(__name__) expected_prefix = journal_source_state_prefix(source) with app.test_request_context(): g.identity = _pl_identity() resolved, derived_prefix = require_ingest_identity(expected_prefix) assert resolved["fingerprint"] == FINGERPRINT assert derived_prefix == expected_prefix def test_require_ingest_identity_failure_cases(journal_env): app = Flask(__name__) _assert_ingest_identity_case(app, IngestIdentityCase.MISSING_AUTH) _assert_ingest_identity_case( app, IngestIdentityCase.MISSING_AUTH, headers={"Authorization": "Basic xyz"}, ) _assert_ingest_identity_case( app, IngestIdentityCase.INVALID_API_KEY, headers={"Authorization": "Bearer does-not-exist"}, ) revoked_key = "revoked1-test-key" revoked_source = _source("revoked-dl", revoked_key) revoked_source["revoked"] = True revoked_source["revoked_at"] = now_ms() assert save_journal_source(revoked_source) is True _assert_ingest_identity_case( app, IngestIdentityCase.DL_REVOKED, headers={"Authorization": f"Bearer {revoked_key}"}, ) _assert_ingest_identity_case( app, IngestIdentityCase.INVALID_PL_IDENTITY, identity=_pl_identity(FINGERPRINT_2), ) revoked_pl = _pl_source(revoked=True, revoked_at=now_ms()) assert save_journal_source(revoked_pl) is True _assert_ingest_identity_case( app, IngestIdentityCase.PL_REVOKED, identity=_pl_identity(FINGERPRINT), ) disabled_pl = _pl_source(fingerprint=FINGERPRINT_2, enabled=False) assert save_journal_source(disabled_pl) is True _assert_ingest_identity_case( app, IngestIdentityCase.PL_DISABLED, identity=_pl_identity(FINGERPRINT_2), ) mismatch_key = "abcd1234-valid-key" mismatch_source = _source("mismatch-dl", mismatch_key) assert save_journal_source(mismatch_source) is True _assert_ingest_identity_case( app, IngestIdentityCase.PREFIX_MISMATCH, headers={"Authorization": f"Bearer {mismatch_key}"}, key_prefix="deadbeef", ) def test_create_and_load(journal_env): key = generate_key() source = _source("alpha", key, created_at=123) assert save_journal_source(source) is True loaded = load_journal_source(key) assert loaded is not None assert {k: v for k, v in loaded.items() if k != "filename_prefix"} == source assert loaded["filename_prefix"] == key[:8] source_path = journal_env / "apps" / "import" / "journal_sources" / "alpha.json" assert source_path.exists() assert stat.S_IMODE(source_path.stat().st_mode) == 0o600 def test_load_wrong_key(journal_env): source = _source("alpha", generate_key(), created_at=123) assert save_journal_source(source) is True assert load_journal_source(generate_key()) is None def test_save_and_load_pl_journal_source(journal_env): source = _pl_source(created_at=123) assert save_journal_source(source) is True loaded = load_journal_source_by_fingerprint(FINGERPRINT) assert loaded is not None assert loaded["pair_mode"] == "pl" assert loaded["fingerprint"] == FINGERPRINT assert loaded["device_label"] == "peer laptop" assert loaded["filename_prefix"] == "a" * 16 assert "key" not in loaded source_path = ( journal_env / "apps" / "import" / "journal_sources" / f"{'a' * 16}.json" ) assert source_path.exists() assert stat.S_IMODE(source_path.stat().st_mode) == 0o600 def test_load_journal_source_by_fingerprint_miss(journal_env): assert load_journal_source_by_fingerprint(FINGERPRINT) is None @pytest.mark.parametrize( "source", [ { "pair_mode": "pl", "key": "abcdef123456", "fingerprint": FINGERPRINT, }, { "name": "empty", "enabled": True, }, ], ) def test_invalid_key_fingerprint_xor_records_rejected(journal_env, source): assert save_journal_source(source) is False assert list_journal_sources() == [] def test_fingerprint_without_pl_pair_mode_rejected(journal_env): source = _pl_source() source.pop("pair_mode") assert save_journal_source(source) is False assert list_journal_sources() == [] def test_pl_journal_source_with_peer_instance_id_loads(journal_env): source = _pl_source(peer_instance_id="abc-123") assert save_journal_source(source) is True loaded = load_journal_source_by_fingerprint(FINGERPRINT) assert loaded is not None assert loaded["peer_instance_id"] == "abc-123" @pytest.mark.parametrize("peer_instance_id", ["", "x" * 257, 123]) def test_invalid_peer_instance_id_records_rejected(journal_env, peer_instance_id): source = _pl_source(peer_instance_id=peer_instance_id) assert save_journal_source(source) is False assert list_journal_sources() == [] def test_peer_instance_id_on_dl_record_rejected(journal_env): source = _source("alpha", generate_key(), created_at=123) source["peer_instance_id"] = "abc-123" assert save_journal_source(source) is False assert list_journal_sources() == [] def test_dl_journal_source_without_peer_instance_id_still_loads(journal_env): source = _source("alpha", generate_key(), created_at=123) assert save_journal_source(source) is True loaded = load_journal_source(source["key"]) assert loaded is not None assert "peer_instance_id" not in loaded def test_list_journal_sources(journal_env): first = _source("first", generate_key(), created_at=100) second = _source("second", generate_key(), created_at=300) third = _source("third", generate_key(), created_at=200) assert save_journal_source(first) is True assert save_journal_source(second) is True assert save_journal_source(third) is True assert [source["name"] for source in list_journal_sources()] == [ "second", "third", "first", ] def test_find_by_name(journal_env): source = _source("alpha", generate_key(), created_at=123) assert save_journal_source(source) is True found = find_journal_source_by_name("alpha") assert found is not None assert {k: v for k, v in found.items() if k != "filename_prefix"} == source assert find_journal_source_by_name("nonexistent") is None def test_create_state_directory(journal_env): state_dir = create_state_directory(journal_env, "abcd1234") source_path = state_dir / "source.json" assert source_path.exists() assert json.loads(source_path.read_text(encoding="utf-8")) == {} for area in STATE_AREAS: state_path = state_dir / area / "state.json" assert state_path.exists() assert json.loads(state_path.read_text(encoding="utf-8")) == {} def test_create_state_directory_preserves_existing_files(journal_env): state_dir = create_state_directory(journal_env, "abcd1234") (state_dir / "source.json").write_text('{"source":"keep"}', encoding="utf-8") segment_state = state_dir / "segments" / "state.json" segment_state.write_text('{"20260520":{}}', encoding="utf-8") create_state_directory(journal_env, "abcd1234") assert json.loads((state_dir / "source.json").read_text("utf-8")) == { "source": "keep" } assert json.loads(segment_state.read_text("utf-8")) == {"20260520": {}} def test_registry_reloads_after_external_write(journal_env): first = _source("alpha", generate_key(), created_at=100) assert save_journal_source(first) is True assert find_journal_source_by_name("beta") is None beta_key = generate_key() beta = _source("beta", beta_key, created_at=200) beta_path = journal_env / "apps" / "import" / "journal_sources" / "beta.json" beta_path.write_text(json.dumps(beta, indent=2), encoding="utf-8") loaded = find_journal_source_by_name("beta") assert loaded is not None assert loaded["key"] == beta_key @pytest.mark.parametrize( ("filename", "source"), [ ("wrong-dl.json", _source("right-dl", "abcdef1234567890", created_at=123)), ("wrong-pl.json", _pl_source(FINGERPRINT_2, created_at=123)), ], ) def test_registry_skips_filename_mismatch(journal_env, caplog, filename, source): caplog.set_level(logging.WARNING) source_path = journal_env / "apps" / "import" / "journal_sources" / filename source_path.write_text(json.dumps(source), encoding="utf-8") assert list_journal_sources() == [] assert "mismatched filename" in caplog.text def test_duplicate_name_rejected(journal_env): source = _source("alpha", generate_key(), created_at=123) assert save_journal_source(source) is True assert find_journal_source_by_name("alpha")["key"] == source["key"] def test_invalid_name_rejected(journal_env): assert is_valid_journal_source_name("../alpha") is False assert ( save_journal_source(_source("../alpha", generate_key(), created_at=123)) is False ) assert find_journal_source_by_name("../alpha") is None assert not (journal_env.parent / "alpha.json").exists() def test_revoke_sets_fields(journal_env): key = generate_key() source = _source("alpha", key, created_at=123) assert save_journal_source(source) is True revoked_at = now_ms() source["revoked"] = True source["revoked_at"] = revoked_at assert save_journal_source(source) is True loaded = load_journal_source(key) assert loaded is not None assert loaded["revoked"] is True assert loaded["revoked_at"] == revoked_at def test_auth_decorator_valid_key(journal_env): key = generate_key() source = _source("alpha", key, created_at=123) assert save_journal_source(source) is True app = Flask(__name__) @app.route("/protected") @require_journal_source def protected(): return jsonify({"name": g.journal_source["name"]}) response = app.test_client().get( "/protected", headers={"Authorization": f"Bearer {key}"}, ) assert response.status_code == 200 assert response.get_json() == {"name": "alpha"} def test_auth_decorator_missing_key(journal_env): app = Flask(__name__) @app.route("/protected") @require_journal_source def protected(): return jsonify({"name": g.journal_source["name"]}) response = app.test_client().get("/protected") assert response.status_code == 401 def test_auth_decorator_invalid_key(journal_env): app = Flask(__name__) @app.route("/protected") @require_journal_source def protected(): return jsonify({"name": g.journal_source["name"]}) response = app.test_client().get( "/protected", headers={"Authorization": "Bearer does-not-exist"}, ) assert response.status_code == 401 def test_auth_decorator_revoked_key(journal_env): key = generate_key() source = _source("alpha", key, created_at=123) source["revoked"] = True source["revoked_at"] = now_ms() assert save_journal_source(source) is True app = Flask(__name__) @app.route("/protected") @require_journal_source def protected(): return jsonify({"name": g.journal_source["name"]}) response = app.test_client().get( "/protected", headers={"Authorization": f"Bearer {key}"}, ) assert response.status_code == 403 def test_auth_decorator_valid_pl_identity(journal_env): assert save_journal_source(_pl_source()) is True app = _auth_app() response = app.test_client().get( "/protected", environ_overrides={"pl.identity": _pl_identity()}, ) assert response.status_code == 200 assert response.get_json() == { "name": None, "device_label": "peer laptop", "pair_mode": "pl", } def test_auth_decorator_unknown_pl_identity_returns_401(journal_env): app = _auth_app() response = app.test_client().get( "/protected", environ_overrides={"pl.identity": _pl_identity()}, ) assert response.status_code == 401 def test_auth_decorator_revoked_pl_identity_returns_403(journal_env): source = _pl_source(revoked=True, revoked_at=now_ms()) assert save_journal_source(source) is True app = _auth_app() response = app.test_client().get( "/protected", environ_overrides={"pl.identity": _pl_identity()}, ) assert response.status_code == 403 def test_auth_decorator_disabled_pl_identity_returns_403(journal_env): source = _pl_source(enabled=False) assert save_journal_source(source) is True app = _auth_app() response = app.test_client().get( "/protected", environ_overrides={"pl.identity": _pl_identity()}, ) assert response.status_code == 403 def test_auth_decorator_pl_identity_precedes_invalid_bearer(journal_env): assert save_journal_source(_pl_source()) is True app = _auth_app() response = app.test_client().get( "/protected", headers={"Authorization": "Bearer does-not-exist"}, environ_overrides={"pl.identity": _pl_identity()}, ) assert response.status_code == 200 assert response.get_json()["pair_mode"] == "pl" @pytest.mark.parametrize("area", STATE_AREAS) def test_manifest_empty_state(manifest_app, manifest_env, area): response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/{area}", headers={"Authorization": f"Bearer {manifest_env['key']}"}, ) assert response.status_code == 200 assert response.get_json() == {} def test_manifest_populated_state(manifest_app, manifest_env): data = {"days": {"2026-04-01": {"count": 5}}} state_path = ( get_state_directory(manifest_env["key"][:8]) / "segments" / "state.json" ) state_path.write_text(json.dumps(data), encoding="utf-8") response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/segments", headers={"Authorization": f"Bearer {manifest_env['key']}"}, ) assert response.status_code == 200 assert response.get_json() == data def test_manifest_missing_state_file(manifest_app, manifest_env): state_path = ( get_state_directory(manifest_env["key"][:8]) / "segments" / "state.json" ) state_path.unlink() response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/segments", headers={"Authorization": f"Bearer {manifest_env['key']}"}, ) assert response.status_code == 200 assert response.get_json() == {} def test_manifest_malformed_json(manifest_app, manifest_env): state_path = ( get_state_directory(manifest_env["key"][:8]) / "segments" / "state.json" ) state_path.write_text("not valid json{{{", encoding="utf-8") response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/segments", headers={"Authorization": f"Bearer {manifest_env['key']}"}, ) assert response.status_code == 200 assert response.get_json() == {} def test_manifest_invalid_area(manifest_app, manifest_env): response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/invalid_area", headers={"Authorization": f"Bearer {manifest_env['key']}"}, ) assert response.status_code == 404 body = response.get_json() assert body["reason_code"] == INVALID_REQUEST_VALUE.code def test_manifest_key_prefix_mismatch(manifest_app, manifest_env): other_prefix = "deadbeef" assert other_prefix != manifest_env["key"][:8] response = manifest_app.test_client().get( f"/journal/{other_prefix}/manifest/segments", headers={"Authorization": f"Bearer {manifest_env['key']}"}, ) assert response.status_code == 403 def test_manifest_pl_identity_uses_fingerprint_prefix(manifest_app, manifest_env): source = _pl_source(FINGERPRINT_2) assert save_journal_source(source) is True prefix = journal_source_state_prefix(source) create_state_directory(manifest_env["root"], prefix) response = manifest_app.test_client().get( f"/journal/{prefix}/manifest/segments", environ_overrides={"pl.identity": _pl_identity(FINGERPRINT_2)}, ) assert response.status_code == 200 assert response.get_json() == {} def test_manifest_pl_identity_wrong_prefix_returns_403(manifest_app, manifest_env): source = _pl_source(FINGERPRINT_2) assert save_journal_source(source) is True create_state_directory(manifest_env["root"], journal_source_state_prefix(source)) response = manifest_app.test_client().get( "/journal/deadbeef/manifest/segments", environ_overrides={"pl.identity": _pl_identity(FINGERPRINT_2)}, ) assert response.status_code == 403 def test_manifest_auth_missing(manifest_app, manifest_env): response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/segments" ) assert response.status_code == 401 def test_manifest_auth_invalid(manifest_app, manifest_env): response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/segments", headers={"Authorization": "Bearer does-not-exist"}, ) assert response.status_code == 401 def test_manifest_auth_revoked(manifest_app, manifest_env): source = manifest_env["source"] source["revoked"] = True source["revoked_at"] = now_ms() assert save_journal_source(source) is True response = manifest_app.test_client().get( f"/journal/{manifest_env['key'][:8]}/manifest/segments", headers={"Authorization": f"Bearer {manifest_env['key']}"}, ) assert response.status_code == 403