Apply the approved Implementation Baseline 1.1 architecture revisions onto the current mainline, verified faithful to the delivered change bundle: - Add aios_baseline: signed owner-delegation-grant.v1 / operational-epoch.v1 / task-principal.v1 auth chain, runtime contract + deployment-truth evaluator, declarative operation registry (effect-class + fail-closed dispatch), lineage ledger, release/recipe/saga ledger, bounded optimization controller, authenticated HTTP transport, resident worker loop and systemd host probe. - Extend existing Job authority (aios_gitops_job_controller/executor) with durable intent/receipt/reconcile and fail-closed admission; harden task_plane/store heartbeat CAS and terminal-state fencing; make reconciliation_controller fail-closed on incomplete/drift evidence. - Add isolated-validation profile templates (deploy/baseline-v1.1, systemd .example), source change/rollback tooling (tools/baseline_v1_1), the AT-01..AT-23 acceptance matrix, M0-M5 runbook, installation/rollback docs and the baseline_v1_1 test suite. - Keep legacy write authorities untouched; isolated-validation profile only. Staged blobs verified byte-identical to the delivered source-changes bundle. Cross-platform baseline tests pass; systemd/fcntl-dependent paths require the declared Linux x86_64 + CPython 3.12 + systemd runtime (site-bound).
72 lines
3.8 KiB
Python
72 lines
3.8 KiB
Python
from pathlib import Path
|
|
import os
|
|
import sys
|
|
import time
|
|
import pytest
|
|
|
|
from aios_baseline.worker_policy import WorkerProfile, eligible
|
|
from aios_baseline.host import SystemdHost, HostError
|
|
|
|
|
|
def profile(**changes):
|
|
value = dict(worker_id='worker-a', identity='machine-a', tenant_scope=['tenant-a'],
|
|
subject_scope=['user-a'], capabilities=['service-status'], priority=10,
|
|
fallback_executor=True, heartbeat_seconds=15, max_concurrency=1)
|
|
value.update(changes)
|
|
return WorkerProfile.from_dict(value)
|
|
|
|
|
|
def test_fallback_expands_only_after_ready_deadline():
|
|
task = dict(tenant_id='tenant-a', subject_id='user-a', operation='service-status', ready_at=100)
|
|
assert not eligible(profile(), task, now=699, last_heartbeat=699)
|
|
assert eligible(profile(), task, now=700, last_heartbeat=700)
|
|
assert eligible(profile(fallback_executor=False), task, now=101, last_heartbeat=101)
|
|
assert not eligible(profile(), task, now=700, last_heartbeat=640)
|
|
|
|
|
|
def test_fallback_cannot_expand_tenant_subject_or_capability():
|
|
task = dict(tenant_id='tenant-a', subject_id='user-b', operation='service-status', ready_at=100)
|
|
assert not eligible(profile(), task, now=800, last_heartbeat=800)
|
|
assert not eligible(profile(), {**task, 'subject_id':'user-a','tenant_id':'tenant-b'}, now=800, last_heartbeat=800)
|
|
assert not eligible(profile(), {**task, 'subject_id':'user-a','operation':'service-restart'}, now=800, last_heartbeat=800)
|
|
|
|
|
|
def systemctl(tmp_path, body):
|
|
path = tmp_path / 'systemctl-fixture'
|
|
path.write_text('#!' + sys.executable + '\n' + body)
|
|
path.chmod(0o700)
|
|
return str(path)
|
|
|
|
|
|
def test_host_status_uses_real_bounded_process_and_no_ambient_credentials(tmp_path, monkeypatch):
|
|
executable = systemctl(tmp_path, "import os,sys\nassert 'AIOS_ADMIN_TOKEN' not in os.environ\nassert sys.argv[-1] == 'sample.service'\nprint('Id=sample.service\\nActiveState=active\\nSubState=running\\nMainPID=123\\nInvocationID=abc')\n")
|
|
monkeypatch.setenv('AIOS_ADMIN_TOKEN','must-not-leak')
|
|
host = SystemdHost({'tenant-a:staging:sample':'sample.service'}, executable=executable)
|
|
result = host.status('sample', 'staging',tenant_id='tenant-a')
|
|
assert result['healthy'] is True
|
|
assert result['properties']['MainPID'] == '123'
|
|
assert result['unit'] == 'sample.service'
|
|
assert 'must-not-leak' not in str(result)
|
|
with pytest.raises(HostError): host.status('sample; rm -rf /', 'staging',tenant_id='tenant-a')
|
|
|
|
|
|
def test_host_nonzero_missing_properties_and_timeout_never_healthy(tmp_path):
|
|
executable = systemctl(tmp_path, "import sys\nprint('Id=sample.service')\nsys.exit(1)\n")
|
|
host = SystemdHost({'tenant-a:staging:sample':'sample.service'}, executable=executable)
|
|
with pytest.raises(HostError): host.status('sample','staging',tenant_id='tenant-a')
|
|
executable = systemctl(tmp_path, "print('Id=sample.service')\n")
|
|
with pytest.raises(HostError): host.status('sample','staging',tenant_id='tenant-a')
|
|
executable = systemctl(tmp_path, "import time\ntime.sleep(5)\n")
|
|
host = SystemdHost({'tenant-a:staging:sample':'sample.service'}, executable=executable, timeout_seconds=0.1)
|
|
start = time.monotonic()
|
|
with pytest.raises(HostError, match='TIMEOUT'): host.status('sample','staging',tenant_id='tenant-a')
|
|
assert time.monotonic()-start < 2
|
|
|
|
|
|
def test_host_kills_output_flood_and_rejects_changed_executable(tmp_path):
|
|
executable=systemctl(tmp_path,"import sys\nsys.stdout.write('X'*200000)\n")
|
|
host=SystemdHost({'tenant-a:staging:sample':'sample.service'},executable=executable)
|
|
with pytest.raises(HostError,match='TOO_LARGE'): host.status('sample','staging',tenant_id='tenant-a')
|
|
Path(executable).write_text('#!'+sys.executable+'\nraise Exception("new unexpected program")\n')
|
|
with pytest.raises(HostError,match='IDENTITY_CHANGED'): host.status('sample','staging',tenant_id='tenant-a')
|