G0~G8 성과·동맹 측정 OS 작업 일괄 고정

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 산출물은 커밋에서 제외했다.
This commit is contained in:
Yun Chan 2026-08-08 01:30:53 +09:00
parent 93dd8f82d7
commit 16e791e044
390 changed files with 243188 additions and 499 deletions

View file

@ -0,0 +1,137 @@
"""Serve a local, synthetic G8 rollback receipt control plane for contract smoke.
This harness never mutates a model or deployment. It only proves that the API
binds a separately authenticated HTTP executor receipt to the pinned command.
It must not be used as production rollback evidence.
"""
from __future__ import annotations
import argparse
import hashlib
import hmac
import json
import re
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from typing import Any
TOKEN_HEADER = "X-Vignette-Rollback-Executor-Token"
MAX_BODY_BYTES = 65_536
SHA256_PATTERN = re.compile(r"^[a-f0-9]{64}$")
REQUIRED_FIELDS = (
"idempotency_key",
"rollback_scope",
"target_kind",
"target_id",
"artifact_record_id",
"artifact_sha256",
)
class HarnessError(ValueError):
pass
def build_synthetic_receipt(payload: Any) -> dict[str, Any]:
if not isinstance(payload, dict):
raise HarnessError("request body must be an object")
if payload.get("schema_version") != "oas.rollback-executor.v1":
raise HarnessError("unsupported rollback executor schema")
missing = [key for key in REQUIRED_FIELDS if not payload.get(key)]
if missing:
raise HarnessError(f"missing required fields: {','.join(missing)}")
if payload["rollback_scope"] not in {"model", "runtime"}:
raise HarnessError("invalid rollback scope")
if payload["target_kind"] not in {"model_change_gate", "release_gate"}:
raise HarnessError("invalid target kind")
if not SHA256_PATTERN.fullmatch(str(payload["artifact_sha256"])):
raise HarnessError("invalid artifact sha256")
binding = "|".join(str(payload[key]) for key in REQUIRED_FIELDS)
execution_id = f"synthetic-g8-{hashlib.sha256(binding.encode()).hexdigest()[:24]}"
return {
"schema_version": "oas.rollback-executor.v1",
"status": "executed",
"execution_id": execution_id,
"idempotency_key": payload["idempotency_key"],
"rollback_scope": payload["rollback_scope"],
"target_kind": payload["target_kind"],
"target_id": payload["target_id"],
"artifact_record_id": payload["artifact_record_id"],
"artifact_sha256": payload["artifact_sha256"],
"evidence_refs": [f"audit://synthetic-g8-control-plane/{execution_id}"],
}
def _handler(*, token: str, mode: str) -> type[BaseHTTPRequestHandler]:
class Handler(BaseHTTPRequestHandler):
def log_message(self, format: str, *args: object) -> None:
return None
def _json(self, status: int, payload: dict[str, Any]) -> None:
body = json.dumps(payload, separators=(",", ":")).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_POST(self) -> None:
if self.path != "/rollback":
self._json(404, {"detail": "not found"})
return
presented = self.headers.get(TOKEN_HEADER, "")
if not hmac.compare_digest(presented, token):
self._json(403, {"detail": "forbidden"})
return
try:
content_length = int(self.headers.get("Content-Length", "0"))
except ValueError:
self._json(400, {"detail": "invalid content length"})
return
if content_length < 1 or content_length > MAX_BODY_BYTES:
self._json(413, {"detail": "request body size rejected"})
return
try:
payload = json.loads(self.rfile.read(content_length))
receipt = build_synthetic_receipt(payload)
except (HarnessError, json.JSONDecodeError) as exc:
self._json(422, {"detail": str(exc)})
return
if mode == "failed":
self._json(503, {"detail": "synthetic executor failure"})
return
self._json(200, receipt)
return Handler
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=18148)
parser.add_argument("--token", required=True)
parser.add_argument("--mode", choices=("executed", "failed"), default="executed")
args = parser.parse_args()
if len(args.token) < 32:
raise SystemExit("--token must contain at least 32 characters")
server = ThreadingHTTPServer(
(args.host, args.port), _handler(token=args.token, mode=args.mode)
)
print(
json.dumps(
{
"ready": True,
"endpoint": f"http://{args.host}:{args.port}/rollback",
"mode": args.mode,
"synthetic_only": True,
},
separators=(",", ":"),
),
flush=True,
)
server.serve_forever()
if __name__ == "__main__":
main()