8월 7일까지 워킹트리에만 남아 있던 미커밋 작업을 커밋한다. 여러 사본 폴더(worktree·clone)에 흩어져 있던 중간 스냅샷을 정리하기 전에 원본을 git 이력으로 고정하는 것이 목적이다. - contracts/routes/services: measurement, outcome_trajectory, rupture_repair, deliberate_practice, calibration_transfer, supervision_research, multimodal_alliance, continuous_improvement 계열 신규 모듈과 테스트 - infra/db/init: 07~16 마이그레이션(측정 기반~calibration transfer 실행) - apps/web: 세션 리뷰 카드·관리 화면·E2E 스펙 추가 - docs/ops: G0~G8 라이브 통합·배포·롤백 증거 문서와 evidence JSON/PNG - scripts: smoke·ledger·릴리스 에이전트·NAS 프리뷰 운영 스크립트 engine.public 로그 .bak과 apps/web/test-results 산출물은 커밋에서 제외했다.
82 lines
3.2 KiB
Python
82 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
SCRIPT = Path(__file__).with_name("provision-outcome-os-runtime-secrets.py")
|
|
SPEC = importlib.util.spec_from_file_location("outcome_secret_provisioner", SCRIPT)
|
|
assert SPEC and SPEC.loader
|
|
MODULE = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(MODULE)
|
|
|
|
|
|
class OutcomeSecretProvisionerTest(unittest.TestCase):
|
|
def test_provision_preserves_unrelated_lines_and_is_idempotent(self) -> None:
|
|
original = "# keep this comment\nSESSION_SECRET=existing-session-secret\n"
|
|
rendered, updated, preserved = MODULE.provision_text(original)
|
|
|
|
self.assertEqual(list(MODULE.TOKEN_KEYS), updated)
|
|
self.assertEqual([], preserved)
|
|
self.assertIn("# keep this comment\n", rendered)
|
|
self.assertIn("SESSION_SECRET=existing-session-secret\n", rendered)
|
|
|
|
second, second_updated, second_preserved = MODULE.provision_text(rendered)
|
|
self.assertEqual(rendered, second)
|
|
self.assertEqual([], second_updated)
|
|
self.assertEqual(list(MODULE.TOKEN_KEYS), second_preserved)
|
|
|
|
def test_short_placeholder_and_duplicate_values_are_rotated(self) -> None:
|
|
duplicate = "x" * 48
|
|
original = "\n".join(
|
|
(
|
|
f"{MODULE.TOKEN_KEYS[0]}=change-me-in-production",
|
|
f"{MODULE.TOKEN_KEYS[1]}=short",
|
|
f"{MODULE.TOKEN_KEYS[2]}={duplicate}",
|
|
f"{MODULE.TOKEN_KEYS[3]}={duplicate}",
|
|
"",
|
|
)
|
|
)
|
|
rendered, updated, preserved = MODULE.provision_text(original)
|
|
values = {
|
|
line.split("=", 1)[0]: line.split("=", 1)[1]
|
|
for line in rendered.splitlines()
|
|
if line and not line.startswith("#")
|
|
}
|
|
|
|
self.assertIn(MODULE.TOKEN_KEYS[0], updated)
|
|
self.assertIn(MODULE.TOKEN_KEYS[1], updated)
|
|
self.assertIn(MODULE.TOKEN_KEYS[3], updated)
|
|
self.assertIn(MODULE.TOKEN_KEYS[2], preserved)
|
|
managed_values = [values[key] for key in MODULE.TOKEN_KEYS]
|
|
self.assertEqual(len(managed_values), len(set(managed_values)))
|
|
self.assertTrue(all(MODULE.is_valid_token(value) for value in managed_values))
|
|
|
|
def test_check_mode_never_mutates_or_emits_values(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temp_name:
|
|
env_file = Path(temp_name) / ".env"
|
|
env_file.write_text("SAFE=value\n", encoding="utf-8")
|
|
before = env_file.read_bytes()
|
|
result = subprocess.run(
|
|
[sys.executable, str(SCRIPT), "--env-file", str(env_file), "--check"],
|
|
check=False,
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
)
|
|
report = json.loads(result.stdout)
|
|
|
|
self.assertEqual(1, result.returncode)
|
|
self.assertEqual(before, env_file.read_bytes())
|
|
self.assertFalse(report["secret_values_emitted"])
|
|
self.assertEqual(list(MODULE.TOKEN_KEYS), report["updated_keys"])
|
|
self.assertNotIn("SAFE=value", result.stdout)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|