from __future__ import annotations import io import json from datetime import datetime, timezone import pytest from sqlmodel import Session, SQLModel, create_engine, select from backend.app.db.models import AuditEvent, Secret from backend.app.services import workmesh_secret_import as importer from backend.app.services.secret_store import get_secret, set_secret REVISION = "a" * 40 CREDENTIAL = "W" * 48 PREFLIGHT_SHA = "b" * 64 BACKUP_SHA = "c" * 64 SECRET_REF = "WORKMESH_DEPLOYMENT_BROKER" TARGET = "jens/workmesh" CHECKS = { "exactMain": "passed", "pushValidation": "passed", "controllerPreflight": "passed", "dataBackup": "passed", } def _valid_preflight(revision: str = REVISION) -> dict[str, object]: return { "apiVersion": "itworx.workmesh-promotion/v2", "status": "preflight_ok", "repository": TARGET, "revision": revision, "preflightSha256": PREFLIGHT_SHA, "backupInputsSha256": BACKUP_SHA, "checks": dict(CHECKS), "diagnostic": CREDENTIAL, } class FakeBroker: def __init__( self, *, response: object | None = None, error: Exception | None = None, base_url: str = "https://controller.example", verify_tls: bool = True, config_error: str | None = None, before_response=None, ): self.response = _valid_preflight() if response is None else response self.error = error self.base_url = base_url self.verify_tls = verify_tls self._config_error = config_error self.before_response = before_response self.preflight_calls: list[tuple[str, str]] = [] self.apply_calls = 0 def configuration_error(self): return self._config_error def workmesh_promotion_preflight(self, revision: str, *, secret: str): self.preflight_calls.append((revision, secret)) if self.before_response is not None: self.before_response() if self.error is not None: raise self.error return self.response def workmesh_promotion_apply(self, *args, **kwargs): self.apply_calls += 1 raise AssertionError("the credential importer must not invoke promotion apply") @pytest.fixture def database(tmp_path, monkeypatch): engine = create_engine(f"sqlite:///{tmp_path / 'workmesh-secret-import.db'}") SQLModel.metadata.create_all(engine) monkeypatch.setattr( importer, "secret_storage_status", lambda: {"productionReady": True} ) with Session(engine) as session: yield engine, session engine.dispose() def _rows(session: Session) -> tuple[Secret | None, list[AuditEvent]]: return ( session.get(Secret, SECRET_REF), list(session.exec(select(AuditEvent)).all()), ) def _database_dump(session: Session) -> str: secret, audits = _rows(session) return repr( { "secret": secret.model_dump() if secret is not None else None, "audits": [event.model_dump() for event in audits], } ) def _import( session: Session, *, credential: str = CREDENTIAL, revision: str = REVISION, broker: FakeBroker | None = None, ): return importer.import_workmesh_deployment_secret( session, credential, revision=revision, broker=broker or FakeBroker(), ) def test_import_creates_encrypted_secret_after_verified_fixed_preflight_and_audits( database, ): _, session = database broker = FakeBroker() result = _import(session, broker=broker) row = session.get(Secret, SECRET_REF) assert result["status"] == "imported" assert result["secretRef"] == SECRET_REF assert result["repository"] == TARGET assert result["revision"] == REVISION assert result["preflightSha256"] == PREFLIGHT_SHA assert result["readback"] == "verified" assert row is not None assert row.encrypted_value != CREDENTIAL assert get_secret(session, SECRET_REF, touch=False) == CREDENTIAL assert broker.preflight_calls == [(REVISION, CREDENTIAL)] assert broker.apply_calls == 0 audits = session.exec(select(AuditEvent)).all() assert len(audits) == 1 audit = audits[0] assert audit.target == TARGET assert audit.result == "success" assert audit.redacted_metadata["storeReference"] == SECRET_REF assert audit.redacted_metadata["revision"] == REVISION assert audit.redacted_metadata["preflightSha256"] == PREFLIGHT_SHA assert CREDENTIAL not in _database_dump(session) def test_identical_import_verifies_and_audits_without_mutating_secret(database): _, session = database assert _import(session)["status"] == "imported" row = session.get(Secret, SECRET_REF) assert row is not None before = { "encrypted_value": row.encrypted_value, "created_at": row.created_at, "updated_at": row.updated_at, "last_used_at": row.last_used_at, "used_by_json": list(row.used_by_json), "metadata_json": dict(row.metadata_json), } result = _import(session) session.refresh(row) assert result["status"] == "already_present" assert { "encrypted_value": row.encrypted_value, "created_at": row.created_at, "updated_at": row.updated_at, "last_used_at": row.last_used_at, "used_by_json": list(row.used_by_json), "metadata_json": dict(row.metadata_json), } == before assert len(session.exec(select(AuditEvent)).all()) == 2 @pytest.mark.parametrize("credential", ["W" * 32, "W" * 256]) def test_credential_length_contract_accepts_exact_boundaries(database, credential): _, session = database result = _import(session, credential=credential) assert result["status"] == "imported" assert get_secret(session, SECRET_REF, touch=False) == credential def test_different_existing_value_is_rejected_before_controller_preflight(database): _, session = database set_secret(session, SECRET_REF, "D" * 48, metadata={"owner": "keep"}) original = session.get(Secret, SECRET_REF) assert original is not None before = original.model_dump() broker = FakeBroker() with pytest.raises(importer.WorkMeshSecretImportError): _import(session, broker=broker) session.rollback() current = session.get(Secret, SECRET_REF) assert current is not None and current.model_dump() == before assert broker.preflight_calls == [] assert session.exec(select(AuditEvent)).all() == [] def test_undecryptable_existing_value_is_rejected_without_replacement(database): _, session = database set_secret(session, SECRET_REF, "D" * 48) row = session.get(Secret, SECRET_REF) assert row is not None row.encrypted_value = "unreadable-ciphertext" session.add(row) session.commit() broker = FakeBroker() with pytest.raises(importer.WorkMeshSecretImportError): _import(session, broker=broker) assert session.get(Secret, SECRET_REF).encrypted_value == "unreadable-ciphertext" assert broker.preflight_calls == [] def test_concurrent_identical_insert_winner_is_retained_and_audited(database): engine, session = database winner_timestamp = datetime(2026, 10, 4, 12, 0, 0, tzinfo=timezone.utc) def concurrent_winner(): with Session(engine) as winner_session: set_secret( winner_session, SECRET_REF, CREDENTIAL, used_by=["concurrent-owner"], metadata={"owner": "concurrent-winner"}, ) winner = winner_session.get(Secret, SECRET_REF) assert winner is not None winner.created_at = winner_timestamp winner.updated_at = winner_timestamp winner_session.add(winner) winner_session.commit() broker = FakeBroker(before_response=concurrent_winner) result = _import(session, broker=broker) winner = session.get(Secret, SECRET_REF) assert result["status"] == "already_present" assert winner is not None assert winner.created_at.replace(tzinfo=timezone.utc) == winner_timestamp assert winner.updated_at.replace(tzinfo=timezone.utc) == winner_timestamp assert winner.used_by_json == ["concurrent-owner"] assert winner.metadata_json == {"owner": "concurrent-winner"} assert get_secret(session, SECRET_REF, touch=False) == CREDENTIAL assert len(session.exec(select(AuditEvent)).all()) == 1 def test_concurrent_different_insert_winner_is_never_overwritten(database): engine, session = database def concurrent_winner(): with Session(engine) as winner_session: set_secret( winner_session, SECRET_REF, "D" * 48, metadata={"owner": "concurrent-winner"}, ) broker = FakeBroker(before_response=concurrent_winner) with pytest.raises(importer.WorkMeshSecretImportError): _import(session, broker=broker) session.rollback() assert get_secret(session, SECRET_REF, touch=False) == "D" * 48 assert session.get(Secret, SECRET_REF).metadata_json == { "owner": "concurrent-winner" } assert session.exec(select(AuditEvent)).all() == [] def test_production_secret_storage_must_be_ready(database, monkeypatch): _, session = database monkeypatch.setattr( importer, "secret_storage_status", lambda: {"productionReady": False} ) broker = FakeBroker() with pytest.raises(importer.WorkMeshSecretImportError): _import(session, broker=broker) assert broker.preflight_calls == [] assert session.get(Secret, SECRET_REF) is None @pytest.mark.parametrize( "credential", [ "W" * 31, "W" * 257, "W" * 31 + " ", "W" * 31 + "\n", "W" * 31 + "\u00e9", "W" * 31 + "\x00", ], ) def test_credential_must_be_bounded_printable_ascii_without_whitespace( database, credential ): _, session = database broker = FakeBroker() with pytest.raises(importer.WorkMeshSecretImportError): _import(session, credential=credential, broker=broker) assert broker.preflight_calls == [] assert session.get(Secret, SECRET_REF) is None @pytest.mark.parametrize("revision", ["main", "A" * 40, "a" * 39, "a" * 41]) def test_revision_must_be_an_exact_full_lowercase_commit(database, revision): _, session = database broker = FakeBroker() with pytest.raises(importer.WorkMeshSecretImportError): _import(session, revision=revision, broker=broker) assert broker.preflight_calls == [] assert session.get(Secret, SECRET_REF) is None @pytest.mark.parametrize( ("base_url", "verify_tls", "config_error"), [ ("http://controller.example", True, None), ("https://controller.example", False, None), ("https://controller.example", True, "deployment_broker_url_invalid"), ], ) def test_preflight_requires_verified_https_configuration( database, base_url, verify_tls, config_error ): _, session = database broker = FakeBroker( base_url=base_url, verify_tls=verify_tls, config_error=config_error, ) with pytest.raises(importer.WorkMeshSecretImportError): _import(session, broker=broker) assert broker.preflight_calls == [] assert session.get(Secret, SECRET_REF) is None @pytest.mark.parametrize( "mutate", [ lambda value: value.update(status="preflight_failed"), lambda value: value.update(apiVersion="wrong/v1"), lambda value: value.update(repository="jens/other"), lambda value: value.update(revision="f" * 40), lambda value: value.update(preflightSha256="invalid"), lambda value: value.update(backupInputsSha256="invalid"), lambda value: value.update(checks={"exactMain": "passed"}), lambda value: value["checks"].update(pushValidation="blocked"), ], ) def test_invalid_fixed_preflight_never_writes_secret_or_audit(database, mutate): _, session = database preflight = _valid_preflight() mutate(preflight) broker = FakeBroker(response=preflight) with pytest.raises(importer.WorkMeshSecretImportError): _import(session, broker=broker) session.rollback() assert session.get(Secret, SECRET_REF) is None assert session.exec(select(AuditEvent)).all() == [] assert broker.apply_calls == 0 def test_non_mapping_preflight_is_rejected_without_storage_write(database): _, session = database broker = FakeBroker(response=["not", "a", "mapping"]) with pytest.raises(importer.WorkMeshSecretImportError): _import(session, broker=broker) session.rollback() assert session.get(Secret, SECRET_REF) is None def test_broker_exception_is_sanitized_and_never_persisted(database): _, session = database broker = FakeBroker(error=RuntimeError(f"upstream leaked {CREDENTIAL}")) with pytest.raises(importer.WorkMeshSecretImportError) as error: _import(session, broker=broker) assert CREDENTIAL not in str(error.value) assert broker.preflight_calls == [(REVISION, CREDENTIAL)] session.rollback() assert session.get(Secret, SECRET_REF) is None assert session.exec(select(AuditEvent)).all() == [] def test_audit_insert_failure_rolls_back_secret_and_audit_together(database): engine, session = database def fail_audit_insert(conn, cursor, statement, parameters, context, executemany): if statement.lstrip().lower().startswith("insert into auditevent"): raise RuntimeError(f"database detail contained {CREDENTIAL}") from sqlalchemy import event event.listen(engine, "before_cursor_execute", fail_audit_insert) try: with pytest.raises(importer.WorkMeshSecretImportError) as error: _import(session) finally: event.remove(engine, "before_cursor_execute", fail_audit_insert) assert CREDENTIAL not in str(error.value) session.rollback() with Session(engine) as verify: assert verify.get(Secret, SECRET_REF) is None assert verify.exec(select(AuditEvent)).all() == [] def test_uncertain_readback_returns_blocked_without_replacing_committed_secret( database, monkeypatch ): engine, session = database actual_get_secret = importer.get_secret calls = 0 def fail_readback_once(db_session, name, *, touch=False): nonlocal calls calls += 1 if calls == 2: return None return actual_get_secret(db_session, name, touch=touch) monkeypatch.setattr(importer, "get_secret", fail_readback_once) broker = FakeBroker() with pytest.raises(importer.WorkMeshSecretImportError) as error: _import(session, broker=broker) assert CREDENTIAL not in str(error.value) monkeypatch.setattr(importer, "get_secret", actual_get_secret) session.rollback() with Session(engine) as verify: row = verify.get(Secret, SECRET_REF) assert row is not None before = row.model_dump() assert get_secret(verify, SECRET_REF, touch=False) == CREDENTIAL assert len(verify.exec(select(AuditEvent)).all()) == 1 outcome = _import(session, broker=FakeBroker()) assert outcome["status"] == "already_present" session.expire_all() after = session.get(Secret, SECRET_REF) assert after is not None and after.model_dump() == before def test_uncertain_commit_returns_blocked_and_same_value_replay_does_not_replace( database, monkeypatch ): engine, session = database actual_commit = session.commit def commit_then_lose_acknowledgement(): if any(isinstance(item, AuditEvent) for item in session.new): actual_commit() raise RuntimeError(f"commit acknowledgement lost for {CREDENTIAL}") actual_commit() monkeypatch.setattr(session, "commit", commit_then_lose_acknowledgement) with pytest.raises(importer.WorkMeshSecretImportError) as error: _import(session) assert CREDENTIAL not in str(error.value) monkeypatch.setattr(session, "commit", actual_commit) with Session(engine) as verify: row = verify.get(Secret, SECRET_REF) assert row is not None before = row.model_dump() assert get_secret(verify, SECRET_REF, touch=False) == CREDENTIAL assert len(verify.exec(select(AuditEvent)).all()) == 1 result = _import(session, broker=FakeBroker()) assert result["status"] == "already_present" session.expire_all() after = session.get(Secret, SECRET_REF) assert after is not None and after.model_dump() == before assert len(session.exec(select(AuditEvent)).all()) == 2 def test_cli_imports_stdin_only_and_emits_sanitized_verification(database, monkeypatch): engine, _ = database broker = FakeBroker() monkeypatch.setattr(importer, "engine", engine) monkeypatch.setattr(importer, "DeploymentBrokerClient", lambda: broker) output = io.StringIO() exit_code = importer.main( [REVISION], stdin=io.BytesIO(CREDENTIAL.encode("ascii")), stdout=output, ) result = json.loads(output.getvalue()) assert exit_code == 0 assert result["status"] == "imported" assert result["secretRef"] == SECRET_REF assert result["revision"] == REVISION assert CREDENTIAL not in output.getvalue() assert broker.preflight_calls == [(REVISION, CREDENTIAL)] def test_cli_rejects_extra_arguments_before_reading_secret(database, monkeypatch): engine, _ = database broker = FakeBroker() monkeypatch.setattr(importer, "engine", engine) monkeypatch.setattr(importer, "DeploymentBrokerClient", lambda: broker) output = io.StringIO() class UnreadableInput: def read(self, _size): pytest.fail("invalid command line must be rejected before reading stdin") exit_code = importer.main( [REVISION, CREDENTIAL], stdin=UnreadableInput(), stdout=output, ) assert exit_code != 0 assert json.loads(output.getvalue()) == { "reason": "invalid_arguments", "status": "blocked", } assert broker.preflight_calls == [] def test_cli_rejects_non_ascii_stdin_without_calling_controller(database, monkeypatch): engine, _ = database broker = FakeBroker() monkeypatch.setattr(importer, "engine", engine) monkeypatch.setattr(importer, "DeploymentBrokerClient", lambda: broker) output = io.StringIO() exit_code = importer.main( [REVISION], stdin=io.BytesIO(b"W" * 47 + b"\xff"), stdout=output, ) assert exit_code != 0 assert json.loads(output.getvalue()) == { "reason": "invalid_input", "status": "blocked", } assert broker.preflight_calls == [] def test_cli_rejects_oversized_stdin_without_calling_controller(database, monkeypatch): engine, _ = database broker = FakeBroker() monkeypatch.setattr(importer, "engine", engine) monkeypatch.setattr(importer, "DeploymentBrokerClient", lambda: broker) output = io.StringIO() exit_code = importer.main( [REVISION], stdin=io.BytesIO(b"W" * 4097), stdout=output, ) assert exit_code != 0 assert json.loads(output.getvalue())["status"] == "blocked" assert "W" * 48 not in output.getvalue() assert broker.preflight_calls == [] def test_cli_unexpected_error_never_echoes_secret(database, monkeypatch): engine, _ = database broker = FakeBroker(error=RuntimeError(f"unexpected {CREDENTIAL}")) monkeypatch.setattr(importer, "engine", engine) monkeypatch.setattr(importer, "DeploymentBrokerClient", lambda: broker) output = io.StringIO() exit_code = importer.main( [REVISION], stdin=io.BytesIO(CREDENTIAL.encode("ascii")), stdout=output, ) result = json.loads(output.getvalue()) assert exit_code != 0 assert result["status"] == "blocked" assert CREDENTIAL not in output.getvalue() assert "unexpected" not in output.getvalue() assert "traceback" not in output.getvalue().lower() @pytest.mark.parametrize("tampered", [False, True]) def test_cli_unknown_typed_error_code_is_normalized(database, monkeypatch, tampered): engine, _ = database monkeypatch.setattr(importer, "engine", engine) monkeypatch.setattr(importer, "DeploymentBrokerClient", FakeBroker) def fail_import(*args, **kwargs): error = importer.WorkMeshSecretImportError(CREDENTIAL) if tampered: error.code = CREDENTIAL raise error monkeypatch.setattr(importer, "import_workmesh_deployment_secret", fail_import) output = io.StringIO() assert importer.main( [REVISION], stdin=io.BytesIO(CREDENTIAL.encode("ascii")), stdout=output ) == 2 assert json.loads(output.getvalue()) == { "status": "blocked", "reason": "import_failed" } assert CREDENTIAL not in output.getvalue()