Publish curated Unraid-AppOps-Gateway source from ba66029223865607deddc234e283c11127324eb8

This commit is contained in:
Public Source Publisher committed 2026-10-07 01:56:22 +00:00
1 parent 820244dbb3
commit 8dd4b40252
52 files changed
+11814 -288

No files matched your search

+211 -13
View File
@@ -764,6 +764,41 @@ def test_appops_legacy_intent_accepts_only_the_reviewed_dockerfile_blob_pair(
deploy_module._appops_validate_intent_payload(unknown_update)
def test_new_database_pair_keeps_protected_full_and_runtime_intent_proofs_strict(
deploy_module,
):
_repository, _metadata, _source, _main, _backup, intent = (
_appops_rollback_intent_fixture(deploy_module, "c" * 40, "a" * 64)
)
def rebind_migration_proof(value):
proof = value["migrationProof"]
evidence = value["rollbackSnapshot"]["appops_legacy"]
evidence["sourceProofSha256"] = deploy_module._canonical_json_sha256(proof["source"])
evidence["protectedMainSha256"] = deploy_module._canonical_json_sha256(proof["protectedMain"])
evidence["migrationProofSha256"] = deploy_module._canonical_json_sha256(proof)
intent["migrationProof"]["source"]["databaseTree"] = (
"21d29c1799118fdc43946c2b6fd5585ccc2c4db1"
)
rebind_migration_proof(intent)
deploy_module._appops_validate_intent_payload(intent)
weak_protected = copy.deepcopy(intent)
weak_protected["migrationProof"]["protectedMain"]["validationContext"] = (
"Managed validation / partial (push)"
)
rebind_migration_proof(weak_protected)
with pytest.raises(deploy_module.DeployError, match="protected-main proof is invalid"):
deploy_module._appops_validate_intent_payload(weak_protected)
incomplete_runtime = copy.deepcopy(intent)
incomplete_runtime["migrationProof"]["runtime"].pop("healthSha256")
rebind_migration_proof(incomplete_runtime)
with pytest.raises(deploy_module.DeployError, match="legacy runtime proof is invalid"):
deploy_module._appops_validate_intent_payload(incomplete_runtime)
def test_appops_cli_rollback_retries_after_state_write_crash_without_synthetic_receipt(
deploy_module, monkeypatch, tmp_path, capsys
):
@@ -1537,6 +1572,47 @@ def test_appops_state_write_rejects_compare_and_swap_drift(deploy_module, monkey
assert path.read_bytes() == original
def test_registered_legacy_state_cas_drift_preserves_external_state_and_records_recovery(
deploy_module, monkeypatch, tmp_path
):
repository = "jens/quiz-monitor"
request_id = "6f9619ff-8b86-4011-b42d-00c04fc964ff"
revision = "a" * 40
state_root = tmp_path / "state"
state_root.mkdir()
monkeypatch.setattr(deploy_module, "STATE_ROOT", state_root)
monkeypatch.setattr(deploy_module, "_registered_legacy_receipt_key", lambda: b"k" * 32)
project = {
"slug": "quiz-monitor", "branch": "main", "compose_project": "quiz-monitor",
"compose_files": ["docker-compose.yml"],
"containers": ["quiz-monitor-quiz-server-1"],
"source_dir": "/srv/example/appdata/quiz-monitor/source",
"_registered_legacy_request_id": request_id,
"_registered_legacy_authorization": {
"requestId": request_id, "revision": revision,
"expectedStateSha256": "0" * 64,
},
}
path = state_root / "quiz-monitor.json"
external_state = b'{"schema_version":3,"live_revision":"independent-update"}\n'
path.write_bytes(external_state)
with pytest.raises(deploy_module.DeployError, match="compare-and-swap"):
deploy_module.write_state(
repository, project, revision, "failed", "deployment failed",
expected_state_sha256="0" * 64,
)
assert path.read_bytes() == external_state
helper = deploy_module._load_registered_legacy_adoption()
outcome = helper.status(
{"repository": repository, "requestId": request_id},
registry={repository: project}, receipt_key=b"k" * 32, state_root=state_root,
)
assert outcome["status"] == "recovery-required"
assert outcome["reasonCode"] == "controller_state_cas_failed"
def _build_reviewed_appops_seed_history(tmp_path, *, candidate_mutation=None):
"""Build the reviewed DB and Dockerfile transitions without old Git history."""
repository = tmp_path / "reviewed-source.git"
@@ -1601,6 +1677,7 @@ def _build_reviewed_appops_seed_history(tmp_path, *, candidate_mutation=None):
forge_seed_rows = (
b' Policy(id="policy-forge-oidc-provision", action="forge.oidc.provision", target="itworx-forge", voice="blocked", manual="allowed", risk="critical", reason="The fixed Forge OIDC client may be provisioned only by an authenticated manual operator route; voice and generic Authentik mutations remain blocked."),\n',
b' Policy(id="policy-forge-secret-prepare", action="forge.secrets.prepare", target="itworx-forge", voice="blocked", manual="blocked", risk="critical", reason="Preparing the fixed Forge bootstrap secret bundle is default-denied and requires an explicit exact-target manual operator policy; voice remains blocked."),\n',
b' Policy(id="policy-forge-route-stage", action="forge.route.stage", target="itworx-forge", voice="blocked", manual="blocked", risk="critical", reason="Staging the fixed disabled Forge proxy host is default-denied; voice remains blocked."),\n',
)
for row in forge_seed_rows:
assert current_init.count(row) == 1
@@ -1629,7 +1706,15 @@ def _build_reviewed_appops_seed_history(tmp_path, *, candidate_mutation=None):
old_tree = git("rev-parse", f"{old_revision}^{{tree}}")
old_database_tree = git("rev-parse", f"{old_revision}:backend/app/db")
(db / "init_db.py").write_bytes(current_init)
candidate_init = current_init
if candidate_mutation == "previous_reviewed_seed_tree":
route_seed = forge_seed_rows[2]
assert candidate_init.count(route_seed) == 1
candidate_init = candidate_init.replace(route_seed, b"", 1)
elif candidate_mutation == "legacy_database_unchanged":
candidate_init = old_init
(db / "init_db.py").write_bytes(candidate_init)
if candidate_mutation == "extra_database_file":
(db / "unreviewed.py").write_text("UNREVIEWED = True\n", encoding="utf-8")
elif candidate_mutation == "models_content":
@@ -1637,21 +1722,47 @@ def _build_reviewed_appops_seed_history(tmp_path, *, candidate_mutation=None):
elif candidate_mutation == "session_content":
(db / "session.py").write_bytes(normalize(current_db / "session.py") + b"\n# unreviewed\n")
elif candidate_mutation == "init_db_content":
(db / "init_db.py").write_bytes(current_init + b"\n# unreviewed database behavior\n")
(db / "init_db.py").write_bytes(candidate_init + b"\n# unreviewed database behavior\n")
elif candidate_mutation == "forge_policy_changed":
changed_init = current_init.replace(
changed_init = candidate_init.replace(
b'action="forge.oidc.provision"',
b'action="forge.oidc.provision-unreviewed"',
1,
)
assert changed_init != current_init
(db / "init_db.py").write_bytes(changed_init)
elif candidate_mutation in {
"route_stage_manual_allowed", "route_stage_voice_allowed", "route_stage_risk_lowered",
}:
route_seed = forge_seed_rows[2]
replacements = {
"route_stage_manual_allowed": (b'manual="blocked"', b'manual="allowed"'),
"route_stage_voice_allowed": (b'voice="blocked"', b'voice="allowed"'),
"route_stage_risk_lowered": (b'risk="critical"', b'risk="high"'),
}
old_field, new_field = replacements[candidate_mutation]
assert route_seed.count(old_field) == 1
candidate_init = candidate_init.replace(route_seed, route_seed.replace(old_field, new_field, 1), 1)
(db / "init_db.py").write_bytes(candidate_init)
elif candidate_mutation == "unknown_policy_row":
route_seed = forge_seed_rows[2]
unknown_policy = (
b' Policy(id="policy-forge-route-stage-unreviewed", '
b'action="forge.route.stage.unreviewed", target="itworx-forge", '
b'voice="blocked", manual="blocked", risk="critical", '
b'reason="Unreviewed policy row."),\n'
)
assert candidate_init.count(route_seed) == 1
candidate_init = candidate_init.replace(route_seed, route_seed + unknown_policy, 1)
(db / "init_db.py").write_bytes(candidate_init)
elif candidate_mutation == "database_file_mode":
(db / "session.py").chmod(0o755)
elif candidate_mutation == "entrypoint_content":
entrypoint.write_bytes(entrypoint.read_bytes() + b"# unreviewed entrypoint\n")
elif candidate_mutation not in {
None, "dockerfile_one_byte", "dockerfile_legacy_unchanged",
None, "previous_reviewed_seed_tree", "legacy_database_unchanged",
"route_stage_manual_allowed", "route_stage_voice_allowed", "route_stage_risk_lowered",
"unknown_policy_row", "dockerfile_one_byte", "dockerfile_legacy_unchanged",
}:
raise AssertionError("unknown fixture mutation")
@@ -1673,6 +1784,11 @@ def _build_reviewed_appops_seed_history(tmp_path, *, candidate_mutation=None):
(working / "Dockerfile").write_bytes(candidate_dockerfile)
git("add", "--all")
if candidate_mutation == "database_file_mode":
# Windows does not preserve chmod's executable bit on the worktree;
# stage the real Git mode mutation so this remains a meaningful tree
# identity negative fixture on every platform.
git("update-index", "--chmod=+x", "--", "backend/app/db/session.py")
git("commit", "-m", "candidate source")
candidate_revision = git("rev-parse", "HEAD")
git("push", "origin", "HEAD:refs/heads/main")
@@ -1729,7 +1845,7 @@ def test_appops_legacy_source_proof_accepts_the_exact_main_184_dockerfile_update
assert proof == {
"legacyRevision": history["oldRevision"],
"legacyTree": history["oldTree"],
"databaseTree": "c87c9aff5a0f0e55b9209e2f085cf1663876520a",
"databaseTree": "21d29c1799118fdc43946c2b6fd5585ccc2c4db1",
"entrypointBlob": "4f71ff74e67d7f15e3cf6b3e79b654158dfea2f8",
"candidateRevision": history["candidateRevision"],
"composeBlob": "243aee2c6924775bed7706373a5777f4e619e053",
@@ -1755,6 +1871,26 @@ def test_appops_legacy_source_proof_keeps_the_old_dockerfile_candidate_valid(
assert proof["dockerfileBlob"] == "73e083dcfef25402665ace5a0bf07a083cf37432"
def test_appops_legacy_source_proof_keeps_the_previous_reviewed_seed_tree_valid(
deploy_module, monkeypatch, tmp_path
):
history = _build_reviewed_appops_seed_history(
tmp_path, candidate_mutation="previous_reviewed_seed_tree"
)
assert history["oldDatabaseTree"] == "d7f8a6188f6c6e0c69bce0e547df31d36ed84a28"
assert history["candidateDatabaseTree"] == "c87c9aff5a0f0e55b9209e2f085cf1663876520a"
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_REVISION", history["oldRevision"])
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_TREE", history["oldTree"])
proof = deploy_module.verify_appops_legacy_source(
history["repository"],
_reviewed_appops_source_project(deploy_module),
history["candidateRevision"],
)
assert proof["databaseTree"] == "c87c9aff5a0f0e55b9209e2f085cf1663876520a"
def test_appops_legacy_source_proof_rejects_a_one_byte_dockerfile_change(
deploy_module, monkeypatch, tmp_path
):
@@ -1772,12 +1908,59 @@ def test_appops_legacy_source_proof_rejects_a_one_byte_dockerfile_change(
)
def test_appops_schema_compatibility_accepts_the_exact_reviewed_seed_tree_pair(
deploy_module, monkeypatch, tmp_path
def test_appops_legacy_source_bindings_remain_fixed_for_the_new_reviewed_tree(
deploy_module, monkeypatch, tmp_path,
):
history = _build_reviewed_appops_seed_history(tmp_path)
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_REVISION", history["oldRevision"])
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_TREE", history["oldTree"])
mutations = (
("_repository_name", "jens/other-repository"),
("branch", "release"),
("gitea_repository_id", 10),
("source_dir", "/tmp/unreviewed-source"),
("compose_project", "unreviewed-project"),
("compose_files", ["other-compose.yml"]),
("containers", ["OtherContainer"]),
("verify_oci_revision", False),
)
for field, value in mutations:
project = _reviewed_appops_source_project(deploy_module)
project[field] = value
with pytest.raises(deploy_module.DeployError, match="fixed legacy source or resolved Compose inputs"):
deploy_module.verify_appops_legacy_source(
history["repository"], project, history["candidateRevision"],
)
for field, value in (
("APPOPS_DATA_PATH", "/tmp/other-data"),
("APPOPS_PUBLISH_HOST", "127.0.0.1"),
("APPOPS_PROXY_NETWORK", "unreviewed-network"),
):
project = _reviewed_appops_source_project(deploy_module)
project["environment"][field] = value
with pytest.raises(deploy_module.DeployError, match="fixed legacy source or resolved Compose inputs"):
deploy_module.verify_appops_legacy_source(
history["repository"], project, history["candidateRevision"],
)
@pytest.mark.parametrize(
("candidate_mutation", "expected_database_tree"),
[
(None, "21d29c1799118fdc43946c2b6fd5585ccc2c4db1"),
("previous_reviewed_seed_tree", "c87c9aff5a0f0e55b9209e2f085cf1663876520a"),
("legacy_database_unchanged", "d7f8a6188f6c6e0c69bce0e547df31d36ed84a28"),
],
)
def test_appops_schema_compatibility_accepts_only_the_two_reviewed_pairs_or_same_tree(
deploy_module, monkeypatch, tmp_path, candidate_mutation, expected_database_tree,
):
history = _build_reviewed_appops_seed_history(
tmp_path, candidate_mutation=candidate_mutation,
)
assert history["oldDatabaseTree"] == "d7f8a6188f6c6e0c69bce0e547df31d36ed84a28"
assert history["candidateDatabaseTree"] == "c87c9aff5a0f0e55b9209e2f085cf1663876520a"
assert history["candidateDatabaseTree"] == expected_database_tree
assert history["candidateEntrypoint"] == "4f71ff74e67d7f15e3cf6b3e79b654158dfea2f8"
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_REVISION", history["oldRevision"])
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_TREE", history["oldTree"])
@@ -1789,7 +1972,7 @@ def test_appops_schema_compatibility_accepts_the_exact_reviewed_seed_tree_pair(
assert proof == {
"legacyRevision": history["oldRevision"],
"legacyTree": history["oldTree"],
"databaseTree": "c87c9aff5a0f0e55b9209e2f085cf1663876520a",
"databaseTree": expected_database_tree,
"entrypointBlob": "4f71ff74e67d7f15e3cf6b3e79b654158dfea2f8",
"candidateRevision": history["candidateRevision"],
}
@@ -1803,6 +1986,10 @@ def test_appops_schema_compatibility_accepts_the_exact_reviewed_seed_tree_pair(
"session_content",
"init_db_content",
"forge_policy_changed",
"unknown_policy_row",
"route_stage_manual_allowed",
"route_stage_voice_allowed",
"route_stage_risk_lowered",
"database_file_mode",
"entrypoint_content",
],
@@ -1815,10 +2002,13 @@ def test_appops_seed_tree_exception_rejects_every_unreviewed_tree_or_entrypoint_
)
assert history["oldDatabaseTree"] == "d7f8a6188f6c6e0c69bce0e547df31d36ed84a28"
if mutation == "entrypoint_content":
assert history["candidateDatabaseTree"] == "c87c9aff5a0f0e55b9209e2f085cf1663876520a"
assert history["candidateDatabaseTree"] == "21d29c1799118fdc43946c2b6fd5585ccc2c4db1"
assert history["candidateEntrypoint"] != "4f71ff74e67d7f15e3cf6b3e79b654158dfea2f8"
else:
assert history["candidateDatabaseTree"] != "c87c9aff5a0f0e55b9209e2f085cf1663876520a"
assert history["candidateDatabaseTree"] not in {
"c87c9aff5a0f0e55b9209e2f085cf1663876520a",
"21d29c1799118fdc43946c2b6fd5585ccc2c4db1",
}
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_REVISION", history["oldRevision"])
monkeypatch.setattr(deploy_module, "APPOPS_LEGACY_OLD_TREE", history["oldTree"])
@@ -3126,8 +3316,9 @@ def test_deployment_environment_clears_unverified_build_date(deploy_module, tmp_
assert environment["APPOPS_BUILD_DATE"] == ""
def test_deployment_environment_allows_project_build_date_override(deploy_module, tmp_path):
def test_deployment_environment_allows_unverified_project_build_date_override(deploy_module, tmp_path):
project = _project(tmp_path)
project["verify_oci_revision"] = False
project["environment"] = {"APPOPS_BUILD_DATE": "operator-configured-value"}
repository = "jens/unraid-appops-gateway"
revision = "a" * 40
@@ -7573,6 +7764,8 @@ def test_controller_release_identity_is_content_bound(status_module, tmp_path, m
renderer = importlib.util.module_from_spec(renderer_spec)
renderer_spec.loader.exec_module(renderer)
assert renderer._ARTIFACT_FILES == status_module._CONTROLLER_ARTIFACT_FILES
candidate_helper = "prepare_mcp_hub_candidate.py"
assert candidate_helper in status_module._CONTROLLER_ARTIFACT_FILES
forge_first_install_index = status_module._CONTROLLER_ARTIFACT_FILES.index(
"forge_first_install.py"
)
@@ -7588,6 +7781,9 @@ def test_controller_release_identity_is_content_bound(status_module, tmp_path, m
else status_module.ROOT / filename
)
(artifact_root / filename).write_bytes(source.read_bytes())
assert (artifact_root / candidate_helper).read_bytes() == (
status_module.ROOT / candidate_helper
).read_bytes()
monkeypatch.setattr(status_module, "ROOT", artifact_root)
monkeypatch.setattr(status_module, "CONTROLLER_RELEASE_PATH", artifact_root / "controller-release.json")
digest = status_module._controller_artifact_digest()
@@ -7608,7 +7804,9 @@ def test_controller_release_identity_is_content_bound(status_module, tmp_path, m
monkeypatch.setattr(status_module.sys, "argv", ["status_server.py", "--check-artifact"])
status_module.main()
assert "validated controller artifact 2.0.0" in capsys.readouterr().out
(artifact_root / "deploy.py").write_text("tampered", encoding="utf-8")
(artifact_root / candidate_helper).write_text("tampered", encoding="utf-8")
assert status_module._controller_release() is None
(artifact_root / candidate_helper).unlink()
assert status_module._controller_release() is None