CI Pipeline / best-practices (push) Successful in 8s
Auto-version and Release / release (push) Failing after 14s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / lint (push) Failing after 34s
CI Pipeline / canary (push) Successful in 37s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / unit-tests (push) Successful in 1m4s
CI Pipeline / required-checks (push) Successful in 1s
deploy / deploy (push) Successful in 48s
CORRECTION 1: #314 reopened — recall_with_associations mode field defect CONFIRMED in current source and FIXED (mode: association_merged). CORRECTION 3: Gitea credential removed from remote URL (credential helper). TOKEN EXPOSED: yes (in diagnostic output). TOKEN ROTATED: not yet (requires Gitea web UI access). Remote URL now shows username only, no secret. CORRECTION 4: duplicate-release-commit defect ROOT CAUSE: convergence computed warranted bump from commits-since-tag without checking if master version already satisfies the bump. FIX: already-converged guard in version_convergence.py (master version > last tag → no commit). Repo-aware (args.repo passed to read_version/latest_tag). CORRECTION 6: lifecycle terminalization — execution exception now guarantees task terminalizes as failed with evidence (no immortal RUNNING). CORRECTION 7: route instruction task-scoped on RuneTask.route_instruction (NOT shared operator state). Read-only leading-verb override. Isolation tests prove no cross-contamination between interleaved tasks. PL1-01/02/03/05: pl1_records.py (route resolution, proof level, failure class, candidate status), metrics with honest NOT_YET_MEASURABLE semantics, route-instruction learning loop (PE-1789102658-0269 SEED). 1253 tests green; ratchet 352/80 (shrink); henxels clean.
43 lines
2.0 KiB
Python
43 lines
2.0 KiB
Python
"""Surface gateway: enter through any surface with parity + peer check."""
|
|
|
|
import pytest
|
|
|
|
from rune.orchestration.capability import CapabilityNegotiator
|
|
from rune.orchestration.gateway import PeerKeyMismatch, SurfaceGateway
|
|
from rune.orchestration.mapping import MappingStore
|
|
from rune.orchestration.records import SurfaceRecord
|
|
from rune.orchestration.surface import SurfaceRegistry
|
|
|
|
|
|
def test_enter_local_registers_and_negotiates_parity(tmp_path):
|
|
gw = SurfaceGateway(SurfaceRegistry(), CapabilityNegotiator(), MappingStore(tmp_path / "m"))
|
|
entry = gw.enter("local_1", surface_kind="local")
|
|
assert entry.peer_verified is True # local needs no peer key
|
|
assert entry.negotiated
|
|
assert gw.registry.get("local_1") is not None
|
|
|
|
|
|
def test_enter_remote_with_correct_peer_key_passes(tmp_path):
|
|
reg = SurfaceRegistry()
|
|
reg.register(SurfaceRecord(surface_id="sfc_r", external_id="remote_1", kind="remote", peer_key="k_123"))
|
|
gw = SurfaceGateway(reg, CapabilityNegotiator(), MappingStore(tmp_path / "m"))
|
|
entry = gw.enter("remote_1", peer_key="k_123")
|
|
assert entry.peer_verified is True
|
|
|
|
|
|
def test_enter_remote_with_wrong_peer_key_raises(tmp_path):
|
|
reg = SurfaceRegistry()
|
|
reg.register(SurfaceRecord(surface_id="sfc_r", external_id="remote_1", kind="remote", peer_key="k_123"))
|
|
gw = SurfaceGateway(reg, CapabilityNegotiator(), MappingStore(tmp_path / "m"))
|
|
with pytest.raises(PeerKeyMismatch):
|
|
gw.enter("remote_1", peer_key="WRONG")
|
|
|
|
|
|
def test_enter_binds_mapping_and_reuses_on_second_entry(tmp_path):
|
|
gw = SurfaceGateway(SurfaceRegistry(), CapabilityNegotiator(), MappingStore(tmp_path / "m"))
|
|
gw.enter("room_1", external_thread="t1", surface_kind="remote", peer_key="")
|
|
conv1 = gw.mapping_store.by_external("room_1", "t1").internal_conversation_id
|
|
assert conv1
|
|
gw.enter("room_1", external_thread="t1", surface_kind="remote", peer_key="")
|
|
assert gw.mapping_store.by_external("room_1", "t1").internal_conversation_id == conv1
|