Why: an update that stops the old process and overwrites the binary cannot get the previous version back, and a migration the old binary cannot read must be refused before that stop. CI also had no fixed RDM SHA to build from. Evidence: python3 -m unittest tests.test_svc_identity tests.test_svc_recover tests.test_svc_deploy_txn tests.test_lifecycle_pin passed. make test-lifecycle exits 2 when AGENT_PG_TEST_DSN is unset. Impact: installs land in releases/<rid> and current switches with mv -T. Deploy keeps the desired state and rolls back a non-terminal journal. Schema compatFloor above the installed target is refused unless --migrate-schema --confirm is paired with a backup. test-lifecycle fails closed without PostgreSQL and an RDM checkout. Login stays NOT_RUN. Refs: recovery plan r3.1 D2 and D3; Backend feature/d1-identity-open Co-authored-by: Cursor <cursoragent@cursor.com>
44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
"""rdm.pin 格式:只接受固定 SHA,拒绝可执行内容。"""
|
|
import re
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
PIN = Path(__file__).resolve().parents[1] / "tests" / "integration" / "lifecycle" / "rdm.pin"
|
|
HEX40 = re.compile(r"^[0-9a-f]{40}$")
|
|
|
|
|
|
def load_pin(text):
|
|
out = {}
|
|
for line in text.splitlines():
|
|
line = line.strip()
|
|
if not line or line.startswith("#"):
|
|
continue
|
|
if "=" not in line:
|
|
raise ValueError("bad pin line")
|
|
key, value = line.split("=", 1)
|
|
if key not in ("sha", "prev_sha", "legacy_sha"):
|
|
raise ValueError("unknown pin key")
|
|
if not HEX40.match(value):
|
|
raise ValueError("sha must be 40 hex")
|
|
out[key] = value
|
|
if set(out) != {"sha", "prev_sha", "legacy_sha"}:
|
|
raise ValueError("pin keys incomplete")
|
|
return out
|
|
|
|
|
|
class RdmPinTests(unittest.TestCase):
|
|
def test_pin_is_three_fixed_shas(self):
|
|
doc = load_pin(PIN.read_text())
|
|
self.assertEqual(len(doc["sha"]), 40)
|
|
self.assertNotEqual(doc["sha"], doc["legacy_sha"])
|
|
|
|
def test_rejects_url_and_short_sha(self):
|
|
with self.assertRaises(ValueError):
|
|
load_pin("sha=https://example.invalid/repo.git\nprev_sha=" + "a" * 40 + "\nlegacy_sha=" + "b" * 40 + "\n")
|
|
with self.assertRaises(ValueError):
|
|
load_pin("sha=abc\nprev_sha=" + "a" * 40 + "\nlegacy_sha=" + "b" * 40 + "\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|