fix(recovery): bind admitted host and record live provider scope approval
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
This commit is contained in:
tegwick 2026-10-16 07:44:36 +02:00
parent c31d21ba7d
commit a17aa7edc1
15 changed files with 393 additions and 7 deletions

View file

@ -208,3 +208,18 @@ def test_full_new_archive_decrypt_extract_native_database_restore_and_cleanup(st
assert r['container_cleanup_verified'] and r['temporary_plaintext_cleanup_verified']
assert not r['full_service_authentication_proven']
finally:subprocess.run(['docker','rm','--force','--volumes',fixture],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL,timeout=30)
def test_runtime_host_requires_owner_and_exact_machine_binding(monkeypatch):
import hashlib,socket
module=load('identity-bundle')
current=module.profile();current['runtime_host']={'hostname':'verified-node','machine_id_sha256':hashlib.sha256(b'fixture-machine').hexdigest()}
monkeypatch.setattr(module,'profile',lambda:current)
monkeypatch.setattr(module.os,'geteuid',lambda:0);monkeypatch.setattr(socket,'gethostname',lambda:'verified-node')
original=Path.read_bytes
monkeypatch.setattr(Path,'read_bytes',lambda p:b'fixture-machine' if str(p)=='/etc/machine-id' else original(p))
module.require_runtime_host()
monkeypatch.setattr(socket,'gethostname',lambda:'foreign-node')
with pytest.raises(module.Refused):module.require_runtime_host()
monkeypatch.setattr(socket,'gethostname',lambda:'verified-node');monkeypatch.setattr(module.os,'geteuid',lambda:1000)
with pytest.raises(module.Refused):module.require_runtime_host()

View file

@ -113,6 +113,12 @@ def test_missing_independently_recovered_point_refuses_all_expiration():
@pytest.mark.parametrize('action,number',[('publisher',48),('retention',49)])
def test_proposed_ccr_cannot_create_provider_share_or_reader(monkeypatch,action,number):
path=setup.PLATFORM/f'credential-change-requests/CCR-2026-{number:04d}-net-kingdom-backup-{action}.yaml'
from types import SimpleNamespace
import yaml
proposed=yaml.safe_load(path.read_text());proposed['status']='proposed';proposed['review']['comments']=[]
# The negative fixture must stay proposed after the real owner approves a CCR.
original_load=setup.load
monkeypatch.setattr(setup,'load',lambda name,p:SimpleNamespace(validate_ccr=lambda _: (proposed,[],[])) if name=='credential_change' else original_load(name,p))
monkeypatch.setattr(setup.inventory,'caller_credentials',lambda:pytest.fail('unapproved request reached credential read'))
with pytest.raises(setup.Refused):setup.run(action,hashlib.sha256(path.read_bytes()).hexdigest(),{})