Files
awoooi/apps/api/tests/test_runtime_surface_inventory.py
Your Name de3007b768
All checks were successful
CD Pipeline / tests (push) Successful in 1m23s
Code Review / ai-code-review (push) Successful in 15s
CD Pipeline / build-and-deploy (push) Successful in 4m1s
CD Pipeline / post-deploy-checks (push) Successful in 1m33s
feat(governance): 新增 runtime surface 只讀矩陣
2026-06-05 10:23:37 +08:00

229 lines
7.8 KiB
Python

from __future__ import annotations
import json
import pytest
from src.services.runtime_surface_inventory import load_latest_runtime_surface_inventory
def test_load_latest_runtime_surface_inventory_reads_newest_file(tmp_path):
older = _snapshot(generated_at="2026-06-04T00:00:00+08:00", completion=40)
newer = _snapshot(generated_at="2026-06-05T00:00:00+08:00", completion=100)
(tmp_path / "runtime_surface_inventory_2026-06-04.json").write_text(
json.dumps(older),
encoding="utf-8",
)
(tmp_path / "runtime_surface_inventory_2026-06-05.json").write_text(
json.dumps(newer),
encoding="utf-8",
)
loaded = load_latest_runtime_surface_inventory(tmp_path)
assert loaded["generated_at"] == "2026-06-05T00:00:00+08:00"
assert loaded["program_status"]["overall_completion_percent"] == 100
assert loaded["rollups"]["total_surfaces"] == 3
assert loaded["operation_boundaries"]["kubectl_allowed"] is False
def test_runtime_surface_inventory_requires_read_only_mode(tmp_path):
snapshot = _snapshot()
snapshot["program_status"]["read_only_mode"] = False
(tmp_path / "runtime_surface_inventory_2026-06-05.json").write_text(
json.dumps(snapshot),
encoding="utf-8",
)
with pytest.raises(ValueError, match="read_only_mode"):
load_latest_runtime_surface_inventory(tmp_path)
def test_runtime_surface_inventory_requires_blocked_operations(tmp_path):
snapshot = _snapshot()
snapshot["operation_boundaries"]["kubectl_allowed"] = True
(tmp_path / "runtime_surface_inventory_2026-06-05.json").write_text(
json.dumps(snapshot),
encoding="utf-8",
)
with pytest.raises(ValueError, match="operation boundaries"):
load_latest_runtime_surface_inventory(tmp_path)
def test_runtime_surface_inventory_requires_rollup_consistency(tmp_path):
snapshot = _snapshot()
snapshot["rollups"]["by_kind"]["deployment"] = 99
(tmp_path / "runtime_surface_inventory_2026-06-05.json").write_text(
json.dumps(snapshot),
encoding="utf-8",
)
with pytest.raises(ValueError, match="by_kind"):
load_latest_runtime_surface_inventory(tmp_path)
def test_runtime_surface_inventory_requires_secret_redaction(tmp_path):
snapshot = _snapshot()
snapshot["runtime_surfaces"][2]["secret_exposure"] = "none"
(tmp_path / "runtime_surface_inventory_2026-06-05.json").write_text(
json.dumps(snapshot),
encoding="utf-8",
)
with pytest.raises(ValueError, match="secret surfaces"):
load_latest_runtime_surface_inventory(tmp_path)
def test_runtime_surface_inventory_requires_operator_denials(tmp_path):
snapshot = _snapshot()
snapshot["operator_contract"]["must_not_interpret_as"] = ["runtime 執行授權"]
(tmp_path / "runtime_surface_inventory_2026-06-05.json").write_text(
json.dumps(snapshot),
encoding="utf-8",
)
with pytest.raises(ValueError, match="must_not_interpret_as"):
load_latest_runtime_surface_inventory(tmp_path)
def test_runtime_surface_inventory_fails_when_missing(tmp_path):
with pytest.raises(FileNotFoundError):
load_latest_runtime_surface_inventory(tmp_path)
def _snapshot(
*,
generated_at: str = "2026-06-05T00:00:00+08:00",
completion: int = 100,
) -> dict:
return {
"schema_version": "runtime_surface_inventory_v1",
"generated_at": generated_at,
"program_status": {
"overall_completion_percent": completion,
"current_priority": "P1",
"current_task_id": "P1-001",
"next_task_id": "P1-002",
"read_only_mode": True,
},
"source_refs": ["k8s/awoooi-prod/"],
"rollups": {
"total_surfaces": 3,
"by_kind": {"deployment": 1, "ingress": 1, "secret": 1},
"by_status": {"manifest_mapped": 1, "action_required": 2},
"by_evidence_level": {
"committed_manifest": 1,
"missing_manifest": 1,
"live_check_required": 1,
},
"action_required_surface_ids": ["external_nginx_gateway_route", "awoooi_secrets"],
"secret_surface_ids": ["awoooi_secrets"],
"live_check_missing_surface_ids": ["external_nginx_gateway_route", "awoooi_secrets"],
"total_source_components": 1,
"source_components_with_runtime_binding": 1,
},
"runtime_surfaces": [
_surface(
"awoooi_api_deployment",
"deployment",
"manifest_mapped",
"committed_manifest",
"none",
"not_run",
),
_surface(
"external_nginx_gateway_route",
"ingress",
"action_required",
"missing_manifest",
"none",
"required",
),
_surface(
"awoooi_secrets",
"secret",
"action_required",
"live_check_required",
"template_only",
"required",
),
],
"source_runtime_components": [
{
"component_id": "api_fastapi_app",
"display_name": "FastAPI app",
"source_ref": "apps/api/src/main.py",
"component_kind": "api_process",
"runtime_binding": "Deployment/awoooi-api",
"status": "bound",
"next_action": "只讀確認。",
}
],
"evidence_gaps": [
{
"gap_id": "external_gateway_manifest_gap",
"severity": "high",
"status": "action_required",
"summary": "缺外部 gateway manifest。",
"evidence_refs": ["k8s/awoooi-prod/"],
"next_action": "只讀補證據。",
}
],
"operator_contract": {
"display_mode": "read_only_runtime_surface",
"must_not_interpret_as": [
"runtime 執行授權",
"rollout / restart / scale / delete 批准",
"Secret 已驗證或可讀取",
"Ingress / DNS 可修改",
],
"secret_display_policy": "只顯示 redacted metadata。",
},
"operation_boundaries": {
"read_only_api_allowed": True,
"live_k8s_query_allowed": False,
"kubectl_allowed": False,
"rollout_allowed": False,
"restart_allowed": False,
"scale_allowed": False,
"delete_allowed": False,
"secret_read_allowed": False,
"secret_plaintext_allowed": False,
"active_scan_allowed": False,
"production_route_change_allowed": False,
},
"approval_boundaries": {
"sdk_installation_allowed": False,
"paid_api_call_allowed": False,
"shadow_or_canary_allowed": False,
"production_routing_allowed": False,
"destructive_operation_allowed": False,
},
}
def _surface(
surface_id: str,
kind: str,
status: str,
evidence_level: str,
secret_exposure: str,
live_check_status: str,
) -> dict:
return {
"surface_id": surface_id,
"display_name": surface_id,
"kind": kind,
"manifest_ref": "k8s/awoooi-prod/example.yaml",
"status": status,
"risk_level": "high",
"evidence_level": evidence_level,
"runtime_binding": "example runtime binding",
"health_contract": "example health contract",
"secret_exposure": secret_exposure,
"live_check_status": live_check_status,
"evidence_refs": ["k8s/awoooi-prod/example.yaml"],
"next_action": "只讀確認。",
}