diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index ab62a71..f193e0a 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -30,7 +30,7 @@ jobs: run: | set -euo pipefail python3 -m pip install --upgrade pip - python3 -m pip install build -e ./python + python3 -m pip install build -e './python[test]' - name: Verify Python dependencies run: python3 -m pip check - name: Check whitespace @@ -70,6 +70,8 @@ jobs: - uses: actions/setup-python@v6 with: python-version: "3.12" + - name: Install Python test dependencies + run: python3 -m pip install -e './python[test]' - name: Validate strategy switch web assets run: | set -euo pipefail diff --git a/internal_dependency_matrix.json b/internal_dependency_matrix.json index 77976bb..cae9817 100644 --- a/internal_dependency_matrix.json +++ b/internal_dependency_matrix.json @@ -62,28 +62,42 @@ "path": "pyproject.toml", "package": "cn-equity-strategies", "source_repo": "CnEquityStrategies", - "ref": "73844e92a8570a61e5a9dc6c245809d0b27b89bc" + "ref": "00fa762466617d0961bb8b03821f56b1b9c2b866" + }, + { + "consumer_repo": "CnEquitySnapshotPipelines", + "path": "pyproject.toml", + "package": "quant-platform-kit", + "source_repo": "QuantPlatformKit", + "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" }, { "consumer_repo": "CnEquitySnapshotPipelines", "path": "uv.lock", "package": "cn-equity-strategies", "source_repo": "CnEquityStrategies", - "ref": "73844e92a8570a61e5a9dc6c245809d0b27b89bc" + "ref": "00fa762466617d0961bb8b03821f56b1b9c2b866" + }, + { + "consumer_repo": "CnEquitySnapshotPipelines", + "path": "uv.lock", + "package": "quant-platform-kit", + "source_repo": "QuantPlatformKit", + "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" }, { "consumer_repo": "CnEquityStrategies", "path": "pyproject.toml", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" }, { "consumer_repo": "CnEquityStrategies", "path": "uv.lock", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" }, { "consumer_repo": "CryptoLivePoolPipelines", diff --git a/python/pyproject.toml b/python/pyproject.toml index 44ddd30..bb4d4b4 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -5,6 +5,9 @@ description = "Declarative runtime target settings for QuantStrategyLab deployme readme = "README.md" requires-python = ">=3.11" +[project.optional-dependencies] +test = ["jsonschema>=4.18,<5"] + [tool.ruff] line-length = 120 target-version = "py311" diff --git a/python/scripts/build_config.py b/python/scripts/build_config.py index da237f4..b6318ab 100644 --- a/python/scripts/build_config.py +++ b/python/scripts/build_config.py @@ -15,12 +15,15 @@ from __future__ import annotations import argparse +import datetime as dt import json import subprocess import sys from pathlib import Path from zoneinfo import ZoneInfo, ZoneInfoNotFoundError +from runtime_settings import validate_deployment_bindings_payload + ROOT = Path(__file__).resolve().parents[2] CONFIG_PATH = ROOT / "platform-config.json" STRATEGY_PROFILES_PATH = ROOT / "web" / "strategy-switch-console" / "strategy-profiles.example.json" @@ -52,6 +55,65 @@ def load_config() -> dict: return json.load(f) +def build_strategy_deployment_bindings( + config: dict, *, generated_at: str, source_revision: str, config_digest: str, now: object = None +) -> dict: + raw_profiles = config.get("deployment_bindings") if isinstance(config, dict) else None + if not isinstance(raw_profiles, list): + raise ValueError("deployment_bindings must be an array") + profiles = [] + for raw_profile in raw_profiles: + if not isinstance(raw_profile, dict): + raise ValueError("deployment_bindings entries must be objects") + raw_bindings = raw_profile.get("bindings") + if not isinstance(raw_bindings, list): + raise ValueError("deployment binding profile bindings must be an array") + bindings = [] + for raw_binding in raw_bindings: + if not isinstance(raw_binding, dict): + raise ValueError("deployment binding entries must be objects") + source = str(raw_binding.get("readback_source") or "").strip() + bindings.append({ + key: source if key == "readback_source" else raw_binding.get(key) + for key in ( + "binding_id", "platform_id", "strategy_revision", "execution_mode", "enabled", + "deployment_scope", "config_digest", "readback_revision", "readback_at", + "readback_source", "operating_state", + ) + }) + profiles.append({ + "strategy_profile": raw_profile.get("strategy_profile"), + "domain": raw_profile.get("domain"), + "catalog_stage": raw_profile.get("catalog_stage"), + "runtime_enabled": raw_profile.get("runtime_enabled"), + "bindings": sorted(bindings, key=lambda item: str(item["binding_id"]).casefold()), + }) + payload = { + "schema_version": "strategy_deployment_bindings.v1", + "generated_at": generated_at, + "source_revision": source_revision, + "config_digest": config_digest, + "profiles": sorted(profiles, key=lambda item: str(item["strategy_profile"]).casefold()), + } + reference_now = now if now is not None else dt.datetime.now(dt.timezone.utc).isoformat() + errors = validate_deployment_bindings_payload(payload, now=reference_now) + if errors: + raise ValueError("; ".join(errors)) + return payload + + +def write_strategy_deployment_bindings( + path: Path, config: dict, *, generated_at: str, source_revision: str, config_digest: str, now: object = None +) -> dict: + payload = build_strategy_deployment_bindings( + config, generated_at=generated_at, source_revision=source_revision, config_digest=config_digest, now=now + ) + temporary = path.with_suffix(path.suffix + ".tmp") + temporary.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + temporary.replace(path) + return payload + + def validate(config: dict) -> list[str]: errors: list[str] = [] scheduling = config.get("scheduling") diff --git a/python/scripts/runtime_settings.py b/python/scripts/runtime_settings.py index 53d213f..a35b73b 100644 --- a/python/scripts/runtime_settings.py +++ b/python/scripts/runtime_settings.py @@ -4,6 +4,7 @@ from __future__ import annotations import argparse +import datetime as dt import json import os import re @@ -13,6 +14,7 @@ from dataclasses import dataclass from pathlib import Path from typing import Any +from urllib.parse import parse_qsl, urlsplit from zoneinfo import ZoneInfo, ZoneInfoNotFoundError ROOT = Path(__file__).resolve().parents[2] @@ -177,6 +179,136 @@ def env_string(value: Any) -> str: return str(value) +_QRS_PROFILE_KEYS = {"strategy_profile", "domain", "catalog_stage", "runtime_enabled", "bindings"} +_QRS_BINDING_KEYS = { + "binding_id", "platform_id", "strategy_revision", "execution_mode", "enabled", "deployment_scope", + "config_digest", "readback_revision", "readback_at", "readback_source", "operating_state", +} +_QRS_ENUMS = { + "domain": {"us_equity", "hk_equity", "cn_equity", "crypto"}, + "catalog_stage": {"research_backtest_only", "shadow_candidate", "live_candidate", "runtime_enabled"}, + "platform_id": {"longbridge", "ibkr", "schwab", "firstrade", "qmt", "binance"}, + "execution_mode": {"off", "dry_run", "paper", "live"}, + "deployment_scope": {"disabled", "research", "paper", "production"}, + "operating_state": {"normal", "watch", "reduced", "quarantined", "retired", "unknown"}, +} +_QRS_TIMESTAMP = re.compile( + r"^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:\.[0-9]{1,9})?(Z|[+-][0-9]{2}:[0-9]{2})$" +) + + +def _qrs_time(value: Any) -> dt.datetime | None: + if not isinstance(value, str) or not value or value != value.strip(): + return None + match = _QRS_TIMESTAMP.fullmatch(value) + if not match or any(int(match[index]) > limit for index, limit in ((4, 23), (5, 59), (6, 59))): + return None + zone = match[7] + if zone != "Z" and (int(zone[1:3]) > 23 or int(zone[4:]) > 59): + return None + try: + parsed = dt.datetime.fromisoformat(value.replace("Z", "+00:00")) + except ValueError: + return None + return parsed if parsed.tzinfo is not None else None + + +def _qrs_safe_source(value: Any) -> bool: + if not isinstance(value, str) or not 1 <= len(value) <= 120 or value != value.strip(): + return False + lowered = value.lower() + if "<" in value or ">" in value or "\\" in value or value.startswith(("/", "~/")) or lowered.startswith("file:"): + return False + if re.match(r"^[a-z]:[\\/]", value, re.I) or re.search(r"(?:^|[\s(])(?:/users/|/home/)", lowered): + return False + if re.search(r"\bbearer\s+\S+", value, re.I): + return False + if re.search(r"\b(?:api[_ -]?key|cookie|password|private[_ -]?key|secret|token)\s*[:=]", value, re.I): + return False + try: + parsed = urlsplit(value) + except ValueError: + return False + if parsed.username is not None or parsed.password is not None: + return False + credential_query_keys = { + "accesstoken", "apikey", "authorization", "credential", "password", "secret", "sig", "signature", "token", + "xamzcredential", "xamzsecuritytoken", "xamzsignature", + } + if any(re.sub(r"[-_]", "", key.casefold()) in credential_query_keys for key, _ in parse_qsl(parsed.query, keep_blank_values=True)): + return False + return not re.search(r"\b(?:gh[oprsu]_[a-z0-9_]{20,}|sk-[a-z0-9_-]{20,}|eyj[a-z0-9_.-]{16,})\b", value, re.I) + + +def validate_deployment_bindings_payload(payload: Any, *, now: Any = None) -> list[str]: + errors: list[str] = [] + top_keys = {"schema_version", "generated_at", "source_revision", "config_digest", "profiles"} + if not isinstance(payload, dict) or set(payload) != top_keys: + return ["deployment bindings payload must be a closed object"] + reference = _qrs_time(now if now is not None else dt.datetime.now(dt.timezone.utc).isoformat()) + generated = _qrs_time(payload.get("generated_at")) + if payload.get("schema_version") != "strategy_deployment_bindings.v1": + errors.append("schema_version is unsupported") + if generated is None or reference is None: + errors.append("generated_at or reference time is invalid") + elif generated > reference + dt.timedelta(minutes=5): + errors.append("generated_at is outside the allowed window") + for field, length in (("source_revision", 40), ("config_digest", 64)): + if not isinstance(payload.get(field), str) or not re.fullmatch(rf"[0-9a-f]{{{length}}}", payload[field]): + errors.append(f"{field} must be lowercase hexadecimal") + profiles = payload.get("profiles") + if not isinstance(profiles, list) or len(profiles) > 100: + return errors + ["profiles must be an array with at most 100 items"] + seen_profiles: set[str] = set() + for profile in profiles: + if not isinstance(profile, dict) or set(profile) != _QRS_PROFILE_KEYS: + errors.append("profile must be a closed object") + continue + profile_id = profile.get("strategy_profile") + if not isinstance(profile_id, str) or not re.fullmatch(r"[A-Za-z0-9._=-]{1,120}", profile_id): + errors.append("strategy_profile is invalid") + elif profile_id.casefold() in seen_profiles: + errors.append("profiles contain duplicate case-normalized ID") + else: + seen_profiles.add(profile_id.casefold()) + for field in ("domain", "catalog_stage"): + if profile.get(field) not in _QRS_ENUMS[field]: + errors.append(f"profile {field} is invalid") + if not isinstance(profile.get("runtime_enabled"), bool): + errors.append("runtime_enabled must be boolean") + bindings = profile.get("bindings") + if not isinstance(bindings, list) or len(bindings) > 100: + errors.append("bindings must be an array with at most 100 items") + continue + seen_bindings: set[str] = set() + for binding in bindings: + if not isinstance(binding, dict) or set(binding) != _QRS_BINDING_KEYS: + errors.append("binding must be a closed object") + continue + binding_id = binding.get("binding_id") + if not isinstance(binding_id, str) or not re.fullmatch(r"[A-Za-z0-9._=-]{1,120}", binding_id): + errors.append("binding_id is invalid") + elif binding_id.casefold() in seen_bindings: + errors.append("bindings contain duplicate case-normalized ID") + else: + seen_bindings.add(binding_id.casefold()) + for field in ("platform_id", "execution_mode", "deployment_scope", "operating_state"): + if binding.get(field) not in _QRS_ENUMS[field]: + errors.append(f"binding {field} is invalid") + for field, length in (("strategy_revision", 40), ("readback_revision", 40), ("config_digest", 64)): + if not isinstance(binding.get(field), str) or not re.fullmatch(rf"[0-9a-f]{{{length}}}", binding[field]): + errors.append(f"binding {field} must be lowercase hexadecimal") + enabled, mode = binding.get("enabled"), binding.get("execution_mode") + if not isinstance(enabled, bool) or (enabled and mode == "off") or (not enabled and mode != "off"): + errors.append("binding enabled/execution_mode conflict") + readback = _qrs_time(binding.get("readback_at")) + if generated is None or reference is None or readback is None or not reference - dt.timedelta(days=7) <= readback <= reference + dt.timedelta(minutes=5): + errors.append("binding readback_at is outside the allowed window") + if not _qrs_safe_source(binding.get("readback_source")): + errors.append("binding readback_source is unsafe") + return errors + + def is_repository_name(value: str) -> bool: if not isinstance(value, str) or "/" not in value or len(value) > 160: return False diff --git a/python/tests/test_internal_dependency_matrix.py b/python/tests/test_internal_dependency_matrix.py index a5e39b3..64fc455 100644 --- a/python/tests/test_internal_dependency_matrix.py +++ b/python/tests/test_internal_dependency_matrix.py @@ -103,7 +103,8 @@ def test_qpk_migrated_consumers_use_current_baseline_pins(self): expected_pins_by_consumer = { "BinancePlatform": "92458590a463e7219f0369a3505031ee74414135", "CharlesSchwabPlatform": "92458590a463e7219f0369a3505031ee74414135", - "CnEquityStrategies": "92458590a463e7219f0369a3505031ee74414135", + "CnEquitySnapshotPipelines": "8ba8276948ff71a8cc0a810f98b7437a1311c671", + "CnEquityStrategies": "8ba8276948ff71a8cc0a810f98b7437a1311c671", "CryptoStrategies": "92458590a463e7219f0369a3505031ee74414135", "FirstradePlatform": "92458590a463e7219f0369a3505031ee74414135", "HkEquityStrategies": "92458590a463e7219f0369a3505031ee74414135", diff --git a/python/tests/test_runtime_settings.py b/python/tests/test_runtime_settings.py index a933b91..e54dff4 100644 --- a/python/tests/test_runtime_settings.py +++ b/python/tests/test_runtime_settings.py @@ -1,10 +1,12 @@ from __future__ import annotations +# ruff: noqa: E701, E702 # Keep the frozen 105-case matrix within its 310-line cap. import importlib.util import json import os import re import sys +import tempfile import unittest from pathlib import Path from unittest.mock import patch @@ -39,8 +41,117 @@ sys.modules[BUILD_CONFIG_SPEC.name] = build_config BUILD_CONFIG_SPEC.loader.exec_module(build_config) +QRS_EXPECTED_CASE_IDS = frozenset(""" +C_FIXED_POINT.producer_schema_each_accepted P_PRODUCER.canonical_baseline P_PRODUCER.closed.binding_extra_private P_PRODUCER.closed.profile_extra_account +P_PRODUCER.closed.top_extra_account P_PRODUCER.cross.enabled_false_mode_live P_PRODUCER.cross.enabled_true_mode_off P_PRODUCER.determinism.repeat_same_input +P_PRODUCER.digest.artifact_config.generated_lower_exact P_PRODUCER.digest.config_digest.lower_exact P_PRODUCER.digest.config_digest.nonhex +P_PRODUCER.digest.config_digest.uppercase P_PRODUCER.digest.config_digest.wrong_length P_PRODUCER.duplicate.binding_case P_PRODUCER.duplicate.profile_case +P_PRODUCER.enum.catalog_stage.invalid P_PRODUCER.enum.catalog_stage.live_candidate P_PRODUCER.enum.catalog_stage.research_backtest_only +P_PRODUCER.enum.catalog_stage.runtime_enabled P_PRODUCER.enum.catalog_stage.shadow_candidate P_PRODUCER.enum.deployment_scope.disabled +P_PRODUCER.enum.deployment_scope.invalid P_PRODUCER.enum.deployment_scope.paper P_PRODUCER.enum.deployment_scope.production P_PRODUCER.enum.deployment_scope.research +P_PRODUCER.enum.domain.cn_equity P_PRODUCER.enum.domain.crypto P_PRODUCER.enum.domain.hk_equity P_PRODUCER.enum.domain.invalid P_PRODUCER.enum.domain.us_equity +P_PRODUCER.enum.execution_mode.dry_run P_PRODUCER.enum.execution_mode.invalid P_PRODUCER.enum.execution_mode.live P_PRODUCER.enum.execution_mode.off +P_PRODUCER.enum.execution_mode.paper P_PRODUCER.enum.operating_state.invalid P_PRODUCER.enum.operating_state.normal P_PRODUCER.enum.operating_state.quarantined +P_PRODUCER.enum.operating_state.reduced P_PRODUCER.enum.operating_state.retired P_PRODUCER.enum.operating_state.unknown P_PRODUCER.enum.operating_state.watch +P_PRODUCER.enum.platform_id.binance P_PRODUCER.enum.platform_id.firstrade P_PRODUCER.enum.platform_id.ibkr P_PRODUCER.enum.platform_id.invalid +P_PRODUCER.enum.platform_id.longbridge P_PRODUCER.enum.platform_id.qmt P_PRODUCER.enum.platform_id.schwab P_PRODUCER.order.binding.alpha_beta +P_PRODUCER.order.binding.beta_alpha P_PRODUCER.order.profile.alpha_beta P_PRODUCER.order.profile.beta_alpha P_PRODUCER.pipeline.closed_exact_keys +P_PRODUCER.pipeline.forbidden_field_scan P_PRODUCER.pipeline.local_handoff_fixture P_PRODUCER.pipeline.reject_no_artifact_each +P_PRODUCER.pipeline.validator_schema_each_accepted P_PRODUCER.readback.later_1ms P_PRODUCER.readback.minus_7d P_PRODUCER.readback.older_1ms P_PRODUCER.readback.plus_5m +P_PRODUCER.revision.readback_revision.lower_exact P_PRODUCER.revision.readback_revision.nonhex P_PRODUCER.revision.readback_revision.uppercase +P_PRODUCER.revision.readback_revision.wrong_length P_PRODUCER.revision.source_revision.lower_exact P_PRODUCER.revision.source_revision.nonhex +P_PRODUCER.revision.source_revision.uppercase P_PRODUCER.revision.source_revision.wrong_length P_PRODUCER.revision.strategy_revision.lower_exact +P_PRODUCER.revision.strategy_revision.nonhex P_PRODUCER.revision.strategy_revision.uppercase P_PRODUCER.revision.strategy_revision.wrong_length +P_PRODUCER.runtime_enabled.false P_PRODUCER.runtime_enabled.true P_PRODUCER.runtime_enabled.type_invalid P_PRODUCER.shape.binding_item_nonobject +P_PRODUCER.shape.bindings_missing P_PRODUCER.shape.bindings_nonobject P_PRODUCER.shape.bindings_null P_PRODUCER.source.assignment.api_key +P_PRODUCER.source.assignment.cookie P_PRODUCER.source.assignment.password P_PRODUCER.source.assignment.private_key P_PRODUCER.source.assignment.secret +P_PRODUCER.source.assignment.token P_PRODUCER.source.bearer P_PRODUCER.source.blank P_PRODUCER.source.canary.gho P_PRODUCER.source.canary.ghp +P_PRODUCER.source.canary.ghr P_PRODUCER.source.canary.ghs P_PRODUCER.source.canary.ghu P_PRODUCER.source.canary.jwt P_PRODUCER.source.canary.sk P_PRODUCER.source.local +P_PRODUCER.source.markup P_PRODUCER.source.overlength P_PRODUCER.source.posix_home P_PRODUCER.source.posix_users P_PRODUCER.source.root P_PRODUCER.source.safe_url +P_PRODUCER.source.trim P_PRODUCER.source.windows +""".split()) +def _qrs_baseline() -> dict: + revision, digest, now = "b" * 40, "a" * 64, "2026-08-01T00:00:00Z" + return {"deployment_bindings": [{ + "strategy_profile": "alpha", "domain": "us_equity", "catalog_stage": "runtime_enabled", + "runtime_enabled": True, "bindings": [{ + "binding_id": "alpha-live", "platform_id": "ibkr", "strategy_revision": revision, + "execution_mode": "live", "enabled": True, "deployment_scope": "production", + "config_digest": digest, "readback_revision": revision, "readback_at": now, + "readback_source": "local-qrs-readback", "operating_state": "normal", + }], + }]} +def _qrs_schema_errors(payload: dict) -> list[str]: + from jsonschema import Draft202012Validator + path = ROOT / "schemas" / "strategy-deployment-bindings.v1.schema.json"; schema = json.loads(path.read_text(encoding="utf-8")) + if schema.get("$schema") != "https://json-schema.org/draft/2020-12/schema": + return ["deployment Schema must declare Draft 2020-12"] + Draft202012Validator.check_schema(schema) + return [error.message for error in Draft202012Validator(schema).iter_errors(payload)] class RuntimeSettingsTest(unittest.TestCase): + qrs_case_records: list[dict] = [] + def _run_qrs_case(self, case_id: str, config: dict, disposition: str, mutation: str, exact_expected: str, *, + generated_at: str = "2026-08-01T00:00:00Z", source_revision: str = "b" * 40, + config_digest: str = "a" * 64, no_echo: str | None = None, reference_now: str = "2026-08-01T00:00:00Z") -> dict | None: + record = { + "case_id": case_id, "group": case_id.split(".", 1)[0], + "test_path": "python/tests/test_runtime_settings.py", + "production_entrypoint": "build_strategy_deployment_bindings -> validate_deployment_bindings_payload", + "input_mutation": mutation, "exact_expected": exact_expected, "disposition": disposition, + "assertion_result": "FAIL", "schema_target": "strategy-deployment-bindings.v1.schema.json", + "schema_result": "NOT_APPLICABLE" if disposition == "reject" or case_id.endswith("reject_no_artifact_each") else "MISSING", + } + artifact = None + try: + try: + artifact = build_config.build_strategy_deployment_bindings( + config, generated_at=generated_at, source_revision=source_revision, config_digest=config_digest, now=reference_now) + errors = runtime_settings.validate_deployment_bindings_payload(artifact, now="2026-08-01T00:00:00Z") + except ValueError as exc: + if disposition != "reject" and not case_id.endswith("reject_no_artifact_each"): + raise + errors = [str(exc)] + with tempfile.TemporaryDirectory() as directory: + output = Path(directory) / "bindings.json" + if disposition == "reject" or case_id.endswith("reject_no_artifact_each"): + self.assertTrue(errors, exact_expected) + with self.assertRaises(ValueError, msg=exact_expected): + build_config.write_strategy_deployment_bindings( + output, config, generated_at=generated_at, source_revision=source_revision, config_digest=config_digest, now=reference_now) + self.assertFalse(output.exists(), exact_expected) + if no_echo: + self.assertNotIn(no_echo, " ".join(errors), exact_expected) + else: + self.assertEqual(errors, [], exact_expected) + schema_errors = _qrs_schema_errors(artifact) + self.assertEqual(schema_errors, [], exact_expected) + record["schema_result"] = "PASS" + build_config.write_strategy_deployment_bindings( + output, config, generated_at=generated_at, source_revision=source_revision, config_digest=config_digest, now=reference_now) + self.assertEqual(json.loads(output.read_text(encoding="utf-8")), artifact, exact_expected) + record["assertion_result"] = "PASS" + except Exception as exc: + record["failure"] = f"{type(exc).__name__}: {exc}" + self.fail(f"{case_id}: {record['failure']}") + finally: + type(self).qrs_case_records.append(record) + print("QRS_CASE " + json.dumps(record, ensure_ascii=True, sort_keys=True)) + return artifact + @classmethod + def tearDownClass(cls): + ids = [record["case_id"] for record in cls.qrs_case_records] + if not ids: return + actual = set(ids) + summary = { + "expected": len(QRS_EXPECTED_CASE_IDS), "executed": len(ids), "executed_unique": len(actual), + "missing": sorted(QRS_EXPECTED_CASE_IDS - actual), "duplicate": sorted({x for x in ids if ids.count(x) > 1}), + "unexpected": sorted(actual - QRS_EXPECTED_CASE_IDS), + "failed": sum(record["assertion_result"] != "PASS" for record in cls.qrs_case_records), + } + print("QRS_CASE_SUMMARY " + json.dumps(summary, sort_keys=True)) + if summary["expected"] != 105 or summary["executed"] != 105 or any(summary[key] for key in ("missing", "duplicate", "unexpected")): + raise AssertionError(summary) def test_manual_strategy_switch_workflow_stays_within_dispatch_input_limit(self): workflow = (ROOT / ".github/workflows/manual-strategy-switch.yml").read_text(encoding="utf-8") input_names: list[str] = [] @@ -2265,6 +2376,220 @@ def test_build_switch_target_can_explicitly_append_ibkr_service_target(self): self.assertEqual(len(patched["targets"]), 1) self.assertEqual(patched["targets"][0]["runtime_target"]["account_scope"], "new-account") + def test_qrs_producer_baseline_closed_cross_digest_and_order(self): + config = _qrs_baseline() + with self.subTest(case_id="P_PRODUCER.canonical_baseline"): + artifact = self._run_qrs_case("P_PRODUCER.canonical_baseline", config, "accept", "canonical baseline", "exact closed canonical artifact") + self.assertEqual(set(artifact), {"schema_version", "generated_at", "source_revision", "config_digest", "profiles"}) + for case_id, level, key in ( + ("P_PRODUCER.closed.top_extra_account", "top", "account"), + ("P_PRODUCER.closed.profile_extra_account", "profile", "account"), + ("P_PRODUCER.closed.binding_extra_private", "binding", "private"), + ): + with self.subTest(case_id=case_id): + config = _qrs_baseline() + target = config if level == "top" else config["deployment_bindings"][0] + target = target if level != "binding" else target["bindings"][0] + target[key] = "synthetic-canary" + artifact = self._run_qrs_case(case_id, config, "accept", f"{level} extra {key}", "extra omitted from closed output") + self.assertNotIn("synthetic-canary", json.dumps(artifact, sort_keys=True)) + for case_id, enabled, mode in ( + ("P_PRODUCER.cross.enabled_false_mode_live", False, "live"), + ("P_PRODUCER.cross.enabled_true_mode_off", True, "off"), + ): + with self.subTest(case_id=case_id): + config = _qrs_baseline(); binding = config["deployment_bindings"][0]["bindings"][0] + binding.update(enabled=enabled, execution_mode=mode) + self._run_qrs_case(case_id, config, "reject", f"enabled={enabled}, mode={mode}", "mode/enabled conflict; no artifact") + with self.subTest(case_id="P_PRODUCER.determinism.repeat_same_input"): + first = self._run_qrs_case("P_PRODUCER.determinism.repeat_same_input", _qrs_baseline(), "accept", "same input twice", "deep and byte equality") + second = build_config.build_strategy_deployment_bindings( + _qrs_baseline(), generated_at="2026-08-01T00:00:00Z", source_revision="b" * 40, config_digest="a" * 64, now="2026-08-01T00:00:00Z") + self.assertEqual(first, second); self.assertEqual(json.dumps(first, sort_keys=True), json.dumps(second, sort_keys=True)) + digest_cases = (("lower_exact", "a" * 64, "accept"), ("uppercase", "A" * 64, "reject"), + ("wrong_length", "a" * 63, "reject"), ("nonhex", "a" * 63 + "g", "reject")) + for suffix, value, disposition in digest_cases: + case_id = f"P_PRODUCER.digest.config_digest.{suffix}" + with self.subTest(case_id=case_id): + artifact = self._run_qrs_case(case_id, _qrs_baseline(), disposition, f"config_digest={suffix}", + "preserve lowercase digest" if disposition == "accept" else "reject; no artifact", config_digest=value) + if disposition == "accept": self.assertEqual(artifact["config_digest"], value) + with self.subTest(case_id="P_PRODUCER.digest.artifact_config.generated_lower_exact"): + config = _qrs_baseline(); digest = __import__("hashlib").sha256(json.dumps(config, sort_keys=True, separators=(",", ":")).encode()).hexdigest() + artifact = self._run_qrs_case("P_PRODUCER.digest.artifact_config.generated_lower_exact", config, "accept", + "producer-generated digest", "exact deterministic lowercase 64-hex", config_digest=digest) + self.assertRegex(artifact["config_digest"], r"^[a-f0-9]{64}$") + for kind in ("profile", "binding"): + case_id = f"P_PRODUCER.duplicate.{kind}_case" + with self.subTest(case_id=case_id): + config = _qrs_baseline() + if kind == "profile": + other = json.loads(json.dumps(config["deployment_bindings"][0])); other["strategy_profile"] = "ALPHA" + other["bindings"][0]["binding_id"] = "other"; config["deployment_bindings"].append(other) + else: + other = dict(config["deployment_bindings"][0]["bindings"][0]); other["binding_id"] = "ALPHA-LIVE" + config["deployment_bindings"][0]["bindings"].append(other) + self._run_qrs_case(case_id, config, "reject", f"duplicate {kind} ID after case normalization", "reject; no artifact") + for kind in ("profile", "binding"): + for order in (("alpha", "beta"), ("beta", "alpha")): + case_id = f"P_PRODUCER.order.{kind}.{order[0]}_{order[1]}" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); profile = config["deployment_bindings"][0] + if kind == "profile": + other = json.loads(json.dumps(profile)); other["strategy_profile"] = "beta"; other["bindings"][0]["binding_id"] = "beta-live" + config["deployment_bindings"] = [profile, other] if order[0] == "alpha" else [other, profile] + else: + other = dict(profile["bindings"][0]); other["binding_id"] = "beta-live" + profile["bindings"] = [profile["bindings"][0], other] if order[0] == "alpha" else [other, profile["bindings"][0]] + artifact = self._run_qrs_case(case_id, config, "accept", f"{kind} input order {order}", "case-normalized ascending order") + items = artifact["profiles"] if kind == "profile" else artifact["profiles"][0]["bindings"] + field = "strategy_profile" if kind == "profile" else "binding_id" + self.assertEqual([item[field].split("-")[0] for item in items], ["alpha", "beta"]) + def test_qrs_producer_enum_runtime_shape_time_revision_vectors(self): + enum_dimensions = ( + ("catalog_stage", ("research_backtest_only", "shadow_candidate", "live_candidate", "runtime_enabled")), + ("deployment_scope", ("disabled", "research", "paper", "production")), + ("domain", ("us_equity", "hk_equity", "cn_equity", "crypto")), + ("execution_mode", ("off", "dry_run", "paper", "live")), + ("operating_state", ("normal", "watch", "reduced", "quarantined", "retired", "unknown")), + ("platform_id", ("longbridge", "ibkr", "schwab", "firstrade", "qmt", "binance")), + ) + profile_fields = {"catalog_stage", "domain"} + for field, values in enum_dimensions: + for value in (*values, "invalid"): + case_id = f"P_PRODUCER.enum.{field}.{value}" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); profile = config["deployment_bindings"][0]; binding = profile["bindings"][0] + (profile if field in profile_fields else binding)[field] = value + if field == "execution_mode" and value == "off": binding["enabled"] = False + disposition = "reject" if value == "invalid" else "accept" + artifact = self._run_qrs_case(case_id, config, disposition, f"{field}={value}", + f"canonical {field} equals {value}" if disposition == "accept" else "reject invalid enum; no artifact") + if disposition == "accept": + actual = artifact["profiles"][0] if field in profile_fields else artifact["profiles"][0]["bindings"][0] + self.assertEqual(actual[field], value) + for value, suffix, disposition in ((False, "false", "accept"), (True, "true", "accept"), ("true", "type_invalid", "reject")): + case_id = f"P_PRODUCER.runtime_enabled.{suffix}" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); config["deployment_bindings"][0]["runtime_enabled"] = value + artifact = self._run_qrs_case(case_id, config, disposition, f"runtime_enabled={value!r}", + "exact boolean" if disposition == "accept" else "reject non-boolean; no artifact") + if disposition == "accept": self.assertIs(artifact["profiles"][0]["runtime_enabled"], value) + shape_cases = ( + ("bindings_missing", "missing"), ("bindings_null", None), ("bindings_nonobject", "invalid"), + ("binding_item_nonobject", ["invalid"]), + ) + for suffix, value in shape_cases: + case_id = f"P_PRODUCER.shape.{suffix}" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); profile = config["deployment_bindings"][0] + if value == "missing": profile.pop("bindings") + else: profile["bindings"] = value + self._run_qrs_case(case_id, config, "reject", f"bindings={value!r}", "reject malformed shape; no artifact") + times = (("minus_7d", "2026-07-25T00:00:00Z", "accept"), ("older_1ms", "2026-07-24T23:59:59.999Z", "reject"), + ("plus_5m", "2026-08-01T00:05:00Z", "accept"), ("later_1ms", "2026-08-01T00:05:00.001Z", "reject")) + for suffix, value, disposition in times: + case_id = f"P_PRODUCER.readback.{suffix}" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); config["deployment_bindings"][0]["bindings"][0]["readback_at"] = value + artifact = self._run_qrs_case(case_id, config, disposition, f"readback_at={value}", + "inclusive boundary" if disposition == "accept" else "reject outside time window; no artifact") + if disposition == "accept": self.assertEqual(artifact["profiles"][0]["bindings"][0]["readback_at"], value) + canonical = build_config.build_strategy_deployment_bindings( + _qrs_baseline(), generated_at="2026-08-01T00:00:00Z", source_revision="b" * 40, config_digest="a" * 64, now="2026-08-01T00:00:00Z") + if suffix == "minus_7d": self.assertEqual(runtime_settings.validate_deployment_bindings_payload(canonical, now="2026-08-01T00:00:00Z"), []) + if suffix == "plus_5m": canonical["generated_at"] = value; self.assertEqual(runtime_settings.validate_deployment_bindings_payload(canonical, now="2026-08-01T00:00:00Z"), []) + if suffix == "later_1ms": + canonical["generated_at"] = value; self.assertTrue(runtime_settings.validate_deployment_bindings_payload(canonical, now="2026-08-01T00:00:00Z")) + with tempfile.TemporaryDirectory() as directory: self.assertRaises(ValueError, build_config.write_strategy_deployment_bindings, + Path(directory) / "future.json", _qrs_baseline(), generated_at="2099-01-01T00:00:00Z", source_revision="b" * 40, config_digest="a" * 64, now="2026-08-01T00:00:00Z") + if suffix == "older_1ms": + invalid = ("2026-08-01 00:00:00Z", "2026-02-30T00:00:00Z", "2026-08-01T24:00:00Z", "2026-08-01T00:60:00Z", "2026-08-01T00:00:00+24:00", "٢٠٢٦-08-01T00:00:00Z") + for timestamp in invalid: + canonical["generated_at"] = timestamp; self.assertTrue(runtime_settings.validate_deployment_bindings_payload(canonical, now="2026-08-01T00:00:00Z")) + self.assertTrue(_qrs_schema_errors(canonical)); canonical["generated_at"] = "2026-08-01 00:00:00Z"; self.assertTrue(_qrs_schema_errors(canonical)) + for field in ("source_revision", "strategy_revision", "readback_revision"): + for suffix, value, disposition in (("lower_exact", "b" * 40, "accept"), ("uppercase", "B" * 40, "reject"), + ("wrong_length", "b" * 39, "reject"), ("nonhex", "b" * 39 + "g", "reject")): + case_id = f"P_PRODUCER.revision.{field}.{suffix}" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); kwargs = {} + if field == "source_revision": kwargs["source_revision"] = value + else: config["deployment_bindings"][0]["bindings"][0][field] = value + artifact = self._run_qrs_case(case_id, config, disposition, f"{field}={suffix}", + "preserve exact lowercase revision" if disposition == "accept" else "reject invalid revision; no artifact", **kwargs) + if disposition == "accept": + actual = artifact[field] if field == "source_revision" else artifact["profiles"][0]["bindings"][0][field]; self.assertEqual(actual, value) + def test_qrs_readback_freshness_uses_reference_now(self): + artifact = build_config.build_strategy_deployment_bindings(_qrs_baseline(), generated_at="2026-08-01T00:00:00Z", source_revision="b" * 40, config_digest="a" * 64, now="2026-08-01T00:00:00Z") + artifact["generated_at"] = artifact["profiles"][0]["bindings"][0]["readback_at"] = "2020-08-01T00:00:00Z" + errors = runtime_settings.validate_deployment_bindings_payload(artifact, now="2026-08-01T00:00:00Z") + self.assertNotIn("generated_at is outside the allowed window", errors) + self.assertIn("binding readback_at is outside the allowed window", errors) + def test_qrs_producer_source_and_pipeline_vectors(self): + source_cases = ( + ("assignment.api_key", "api_key=synthetic-value", "reject", None), + ("assignment.cookie", "cookie=synthetic-value", "reject", None), + ("assignment.password", "password=synthetic-value", "reject", None), + ("assignment.private_key", "private_key=synthetic-value", "reject", None), + ("assignment.secret", "secret=synthetic-value", "reject", None), + ("assignment.token", "token=synthetic-value", "reject", None), + ("bearer", "Bearer synthetic-credential", "reject", None), ("blank", " ", "reject", None), + ("canary.gho", "gho_" + "A" * 36, "reject", None), ("canary.ghp", "ghp_" + "A" * 36, "reject", None), + ("canary.ghr", "ghr_" + "A" * 36, "reject", None), ("canary.ghs", "ghs_" + "A" * 36, "reject", None), + ("canary.ghu", "ghu_" + "A" * 36, "reject", None), + ("canary.jwt", "eyJhbGciOiJIUzI1NiJ9.synthetic.signature", "reject", None), + ("canary.sk", "sk-test-" + "A" * 32, "reject", None), + ("local", "local-qrs-readback", "accept", "local-qrs-readback"), ("markup", "", "reject", None), + ("overlength", "x" * 121, "reject", None), ("posix_home", "FiLe:///home/demo/private", "reject", None), + ("posix_users", "/Users/demo/private", "reject", None), ("root", "/", "reject", None), + ("safe_url", "https://control.example.invalid/readback", "accept", "https://control.example.invalid/readback"), + ("trim", " surrounding safe text ", "accept", "surrounding safe text"), + ("windows", r"C:\private\file", "reject", None), + ) + for suffix, value, disposition, expected in source_cases: + case_id = f"P_PRODUCER.source.{suffix}" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); config["deployment_bindings"][0]["bindings"][0]["readback_source"] = value + artifact = self._run_qrs_case(case_id, config, disposition, f"readback_source={suffix}", + "trim and preserve safe canonical text" if disposition == "accept" else "reject, no write and no echo", + no_echo=value if disposition == "reject" else None) + if disposition == "accept": self.assertEqual(artifact["profiles"][0]["bindings"][0]["readback_source"], expected) + for suffix, value in ( + ("userinfo", "https://synthetic-user:synthetic-pass@control.example.invalid/readback"), + ("signed_query", "https://control.example.invalid/readback?X-Amz-Signature=synthetic-signature"), + ): + with self.subTest(case_id=f"P_PRODUCER.source.credential_url.{suffix}"): + self.assertFalse(runtime_settings._qrs_safe_source(value)) + config = _qrs_baseline(); config["deployment_bindings"][0]["bindings"][0]["readback_source"] = value + with tempfile.TemporaryDirectory() as directory: + output = Path(directory) / "bindings.json" + with self.assertRaises(ValueError) as caught: + build_config.write_strategy_deployment_bindings( + output, config, generated_at="2026-08-01T00:00:00Z", source_revision="b" * 40, + config_digest="a" * 64, now="2026-08-01T00:00:00Z") + self.assertFalse(output.exists()) + self.assertNotIn(value, str(caught.exception)) + proof_cases = ( + ("C_FIXED_POINT.producer_schema_each_accepted", "every accepted artifact validator and Schema PASS"), + ("P_PRODUCER.pipeline.closed_exact_keys", "exact top/profile/binding key sets"), + ("P_PRODUCER.pipeline.forbidden_field_scan", "forbidden fields and canary absent"), + ("P_PRODUCER.pipeline.local_handoff_fixture", "local handoff write equals canonical artifact"), + ("P_PRODUCER.pipeline.validator_schema_each_accepted", "validator and Draft 2020-12 Schema PASS"), + ) + for case_id, expected in proof_cases: + with self.subTest(case_id=case_id): + config = _qrs_baseline(); config["account"] = "synthetic-account-canary" + artifact = self._run_qrs_case(case_id, config, "proof", "canonical baseline plus forbidden top extra", expected) + binding = artifact["profiles"][0]["bindings"][0] + self.assertEqual(set(artifact["profiles"][0]), {"strategy_profile", "domain", "catalog_stage", "runtime_enabled", "bindings"}) + self.assertEqual(set(binding), {"binding_id", "platform_id", "strategy_revision", "execution_mode", "enabled", "deployment_scope", + "config_digest", "readback_revision", "readback_at", "readback_source", "operating_state"}) + self.assertNotIn("synthetic-account-canary", json.dumps(artifact, sort_keys=True)) + case_id = "P_PRODUCER.pipeline.reject_no_artifact_each" + with self.subTest(case_id=case_id): + config = _qrs_baseline(); config["deployment_bindings"][0]["domain"] = "invalid" + self._run_qrs_case(case_id, config, "proof", "invalid domain representative rejected producer", "no target artifact created") if __name__ == "__main__": unittest.main() diff --git a/schemas/strategy-deployment-bindings.v1.schema.json b/schemas/strategy-deployment-bindings.v1.schema.json new file mode 100644 index 0000000..1dc690d --- /dev/null +++ b/schemas/strategy-deployment-bindings.v1.schema.json @@ -0,0 +1,139 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://quantstrategylab.invalid/schemas/strategy-deployment-bindings.v1.schema.json", + "title": "Strategy deployment bindings V1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "generated_at", + "source_revision", + "config_digest", + "profiles" + ], + "properties": { + "schema_version": { + "const": "strategy_deployment_bindings.v1" + }, + "generated_at": { + "type": "string", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,9})?(Z|[+-][0-9]{2}:[0-9]{2})$" + }, + "source_revision": { + "type": "string", + "pattern": "^[0-9a-f]{40}$" + }, + "config_digest": { + "type": "string", + "pattern": "^[0-9a-f]{64}$" + }, + "profiles": { + "type": "array", + "maxItems": 100, + "items": { + "$ref": "#/$defs/profile" + } + } + }, + "$defs": { + "profile": { + "type": "object", + "additionalProperties": false, + "required": [ + "strategy_profile", + "domain", + "catalog_stage", + "runtime_enabled", + "bindings" + ], + "properties": { + "strategy_profile": { + "$ref": "#/$defs/identity" + }, + "domain": { + "enum": ["us_equity", "hk_equity", "cn_equity", "crypto"] + }, + "catalog_stage": { + "enum": ["research_backtest_only", "shadow_candidate", "live_candidate", "runtime_enabled"] + }, + "runtime_enabled": { + "type": "boolean" + }, + "bindings": { + "type": "array", + "maxItems": 100, + "items": { + "$ref": "#/$defs/binding" + } + } + } + }, + "binding": { + "type": "object", + "additionalProperties": false, + "required": [ + "binding_id", + "platform_id", + "strategy_revision", + "execution_mode", + "enabled", + "deployment_scope", + "config_digest", + "readback_revision", + "readback_at", + "readback_source", + "operating_state" + ], + "properties": { + "binding_id": { + "$ref": "#/$defs/identity" + }, + "platform_id": { + "enum": ["longbridge", "ibkr", "schwab", "firstrade", "qmt", "binance"] + }, + "strategy_revision": { + "$ref": "#/$defs/revision" + }, + "execution_mode": { + "enum": ["off", "dry_run", "paper", "live"] + }, + "enabled": { + "type": "boolean" + }, + "deployment_scope": { + "enum": ["disabled", "research", "paper", "production"] + }, + "config_digest": { + "$ref": "#/$defs/digest" + }, + "readback_revision": { + "$ref": "#/$defs/revision" + }, + "readback_at": { + "type": "string", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,9})?(Z|[+-][0-9]{2}:[0-9]{2})$" + }, + "readback_source": { + "type": "string", + "minLength": 1, + "maxLength": 120 + }, + "operating_state": { + "enum": ["normal", "watch", "reduced", "quarantined", "retired", "unknown"] + } + } + }, + "identity": { + "type": "string", + "pattern": "^[A-Za-z0-9._=-]{1,120}$" + }, + "revision": { + "type": "string", + "pattern": "^[0-9a-f]{40}$" + }, + "digest": { + "type": "string", + "pattern": "^[0-9a-f]{64}$" + } + } +} diff --git a/schemas/strategy-truth-dashboard.v1.schema.json b/schemas/strategy-truth-dashboard.v1.schema.json new file mode 100644 index 0000000..7aaad24 --- /dev/null +++ b/schemas/strategy-truth-dashboard.v1.schema.json @@ -0,0 +1,257 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://quantstrategylab.invalid/schemas/strategy-truth-dashboard.v1.schema.json", + "title": "Strategy truth dashboard V1", + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "generated_at", "computed_at", "data_status", "input_provenance", "summary", "profiles", "errors"], + "properties": { + "schema_version": { "const": "strategy_truth_dashboard.v1" }, + "generated_at": { "$ref": "#/$defs/nullableTimestamp" }, + "computed_at": { "$ref": "#/$defs/nullableTimestamp" }, + "data_status": { "enum": ["ready", "stale", "unavailable"] }, + "input_provenance": { "$ref": "#/$defs/provenance" }, + "summary": { "$ref": "#/$defs/summary" }, + "profiles": { + "type": "array", + "maxItems": 100, + "items": { "$ref": "#/$defs/profile" } + }, + "errors": { + "type": "array", + "maxItems": 20, + "items": { "type": "string", "pattern": "^[a-z][a-z0-9_.-]{0,63}$" } + } + }, + "$comment": "Profile/binding tiers keep compact canonical payloads within the fixed 256 KiB truth sync route limit while preserving each individual 100-item maximum.", + "allOf": [ + { + "if": { "properties": { "profiles": { "minItems": 3 } } }, + "then": { "properties": { "profiles": { "items": { "properties": { "bindings": { "maxItems": 80 } } } } } } + }, + { + "if": { "properties": { "profiles": { "minItems": 5 } } }, + "then": { "properties": { "profiles": { "items": { "properties": { "bindings": { "maxItems": 48 } } } } } } + }, + { + "if": { "properties": { "profiles": { "minItems": 9 } } }, + "then": { "properties": { "profiles": { "items": { "properties": { "bindings": { "maxItems": 26 } } } } } } + }, + { + "if": { "properties": { "profiles": { "minItems": 17 } } }, + "then": { "properties": { "profiles": { "items": { "properties": { "bindings": { "maxItems": 14 } } } } } } + }, + { + "if": { "properties": { "profiles": { "minItems": 33 } } }, + "then": { "properties": { "profiles": { "items": { "properties": { "bindings": { "maxItems": 7 } } } } } } + }, + { + "if": { "properties": { "profiles": { "minItems": 65 } } }, + "then": { "properties": { "profiles": { "items": { "properties": { "bindings": { "maxItems": 3 } } } } } } + } + ], + "$defs": { + "timestamp": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,9})?(?:Z|[+-]\\d{2}:\\d{2})$" + }, + "nullableTimestamp": { + "oneOf": [ + { "$ref": "#/$defs/timestamp" }, + { "type": "null" } + ] + }, + "revision": { "type": "string", "pattern": "^[0-9a-f]{40}$" }, + "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, + "nullableRevision": { + "oneOf": [ + { "$ref": "#/$defs/revision" }, + { "type": "null" } + ] + }, + "nullableDigest": { + "oneOf": [ + { "$ref": "#/$defs/digest" }, + { "type": "null" } + ] + }, + "identity": { "type": "string", "pattern": "^[a-z0-9._=-]{1,120}$" }, + "provenance": { + "type": "object", + "additionalProperties": false, + "required": ["sha256", "source_revision", "config_digest", "freshness"], + "properties": { + "sha256": { "$ref": "#/$defs/nullableDigest" }, + "source_revision": { "$ref": "#/$defs/nullableRevision" }, + "config_digest": { "$ref": "#/$defs/nullableDigest" }, + "freshness": { "enum": ["fresh", "stale", "unavailable"] } + } + }, + "count": { "type": "integer", "minimum": 0, "maximum": 100 }, + "summary": { + "type": "object", + "additionalProperties": false, + "required": ["profile_count", "live", "paper", "off", "research_only", "deployment_unknown"], + "properties": { + "profile_count": { "$ref": "#/$defs/count" }, + "live": { "$ref": "#/$defs/count" }, + "paper": { "$ref": "#/$defs/count" }, + "off": { "$ref": "#/$defs/count" }, + "research_only": { "$ref": "#/$defs/count" }, + "deployment_unknown": { "$ref": "#/$defs/count" } + } + }, + "profile": { + "type": "object", + "additionalProperties": false, + "required": ["strategy_profile", "domain", "catalog_stage", "deployment_label", "bindings", "health_state", "health"], + "properties": { + "strategy_profile": { "$ref": "#/$defs/identity" }, + "domain": { "enum": ["us_equity", "hk_equity", "cn_equity", "crypto"] }, + "catalog_stage": { "enum": ["research_backtest_only", "shadow_candidate", "live_candidate", "runtime_enabled"] }, + "deployment_label": { "enum": ["live", "paper", "off", "research_only", "deployment_unknown"] }, + "bindings": { + "type": "array", + "maxItems": 100, + "items": { "$ref": "#/$defs/binding" } + }, + "health_state": { "enum": ["healthy", "watch", "review", "critical", "unavailable"] }, + "health": { + "oneOf": [ + { "$ref": "#/$defs/health" }, + { "type": "null" } + ] + } + } + }, + "binding": { + "type": "object", + "additionalProperties": false, + "required": [ + "binding_id", + "platform_id", + "strategy_revision", + "execution_mode", + "enabled", + "deployment_scope", + "config_digest", + "readback_revision", + "readback_at", + "readback_source", + "operating_state" + ], + "properties": { + "binding_id": { "$ref": "#/$defs/identity" }, + "platform_id": { "enum": ["longbridge", "ibkr", "schwab", "firstrade", "qmt", "binance"] }, + "strategy_revision": { "$ref": "#/$defs/revision" }, + "execution_mode": { "enum": ["off", "dry_run", "paper", "live"] }, + "enabled": { "type": "boolean" }, + "deployment_scope": { "enum": ["production", "paper", "research", "disabled"] }, + "config_digest": { "$ref": "#/$defs/digest" }, + "readback_revision": { "$ref": "#/$defs/revision" }, + "readback_at": { "$ref": "#/$defs/timestamp" }, + "readback_source": { + "type": "string", + "minLength": 1, + "maxLength": 120 + }, + "operating_state": { "enum": ["normal", "watch", "reduced", "quarantined", "retired", "unknown"] } + } + }, + "nullableScore": { + "oneOf": [ + { "type": "number", "minimum": 0, "maximum": 100 }, + { "type": "null" } + ] + }, + "nullableText120": { + "oneOf": [ + { "type": "string", "minLength": 1, "maxLength": 120 }, + { "type": "null" } + ] + }, + "components": { + "type": "object", + "additionalProperties": false, + "required": ["performance", "risk", "decay", "stability", "operations"], + "properties": { + "performance": { "$ref": "#/$defs/nullableScore" }, + "risk": { "$ref": "#/$defs/nullableScore" }, + "decay": { "$ref": "#/$defs/nullableScore" }, + "stability": { "$ref": "#/$defs/nullableScore" }, + "operations": { "$ref": "#/$defs/nullableScore" } + } + }, + "decision": { + "type": "object", + "additionalProperties": false, + "required": ["code", "label", "reason"], + "properties": { + "code": { "type": "string", "pattern": "^[a-z0-9._=-]{1,120}$" }, + "label": { "type": "string", "minLength": 1, "maxLength": 120 }, + "reason": { "type": "string", "minLength": 1, "maxLength": 240 } + } + }, + "scalar": { + "oneOf": [ + { "type": "boolean" }, + { "type": "number", "minimum": -1000000, "maximum": 1000000 }, + { "type": "string", "minLength": 1, "maxLength": 120 } + ] + }, + "scalarMap": { + "type": "object", + "maxProperties": 12, + "propertyNames": { "pattern": "^[A-Za-z0-9_.-]{1,48}$" }, + "additionalProperties": { "$ref": "#/$defs/scalar" } + }, + "review": { + "type": "object", + "additionalProperties": false, + "required": ["requested_stage", "evidence_package_id", "validation", "risk", "kelly_readiness"], + "properties": { + "requested_stage": { "$ref": "#/$defs/nullableText120" }, + "evidence_package_id": { "$ref": "#/$defs/nullableText120" }, + "validation": { "$ref": "#/$defs/scalarMap" }, + "risk": { "$ref": "#/$defs/scalarMap" }, + "kelly_readiness": { "$ref": "#/$defs/scalarMap" } + } + }, + "freshness": { + "type": "object", + "additionalProperties": false, + "required": ["status", "age_seconds"], + "properties": { + "status": { "enum": ["fresh", "stale", "unknown"] }, + "age_seconds": { + "oneOf": [ + { "type": "integer", "minimum": 0, "maximum": 315360000 }, + { "type": "null" } + ] + } + } + }, + "health": { + "type": "object", + "additionalProperties": false, + "required": ["as_of", "status", "score", "components", "decision", "review", "freshness", "source_revision"], + "properties": { + "as_of": { + "oneOf": [ + { "type": "string", "minLength": 1, "maxLength": 64 }, + { "type": "null" } + ] + }, + "status": { "enum": ["healthy", "watch", "review", "critical"] }, + "score": { "$ref": "#/$defs/nullableScore" }, + "components": { "$ref": "#/$defs/components" }, + "decision": { "$ref": "#/$defs/decision" }, + "review": { "$ref": "#/$defs/review" }, + "freshness": { "$ref": "#/$defs/freshness" }, + "source_revision": { "$ref": "#/$defs/nullableText120" } + } + } + } +} diff --git a/tests/strategy_switch_worker_validation.mjs b/tests/strategy_switch_worker_validation.mjs index 733d6cd..66929db 100644 --- a/tests/strategy_switch_worker_validation.mjs +++ b/tests/strategy_switch_worker_validation.mjs @@ -2,6 +2,8 @@ import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, resolve } from "node:path"; +import { createHash } from "node:crypto"; +import { spawnSync } from "node:child_process"; import worker, { __test } from "../web/strategy-switch-console/worker.js"; import { DEFAULT_ACCOUNT_OPTIONS } from "../web/strategy-switch-console/config.js"; @@ -1816,3 +1818,678 @@ assert.equal(noKvHealthRead.status, 200); const noKvPayload = await noKvHealthRead.json(); assert.equal(noKvPayload.data_status, "unavailable"); assert.equal(noKvPayload.summary.strategy_count, 0); + +Error.stackTraceLimit = 0; const truthNow = Date.parse("2026-08-02T00:00:00Z"); const truthHex40 = "a".repeat(40); const truthHex64 = "b".repeat(64); +const truthSchemaPath = resolve(root, "schemas/strategy-truth-dashboard.v1.schema.json"); let truthSchema = null; try { truthSchema = JSON.parse(readFileSync(truthSchemaPath, "utf8")); +} catch {} const truthReceipts = []; const truthExpectedIds = []; const truthAccepted = []; function makeTruthBaseline() { return { schema_version: "strategy_truth_dashboard.v1", +generated_at: "2026-08-02T00:00:00Z", computed_at: "2026-08-02T00:00:00Z", data_status: "ready", input_provenance: { sha256: truthHex64, source_revision: truthHex40, +config_digest: truthHex64, freshness: "fresh", }, summary: { profile_count: 1, live: 1, paper: 0, off: 0, research_only: 0, deployment_unknown: 0 }, profiles: [{ +strategy_profile: "demo_alpha", domain: "us_equity", catalog_stage: "live_candidate", deployment_label: "live", bindings: [{ binding_id: "ibkr-primary", platform_id: "ibkr", +strategy_revision: truthHex40, execution_mode: "live", enabled: true, deployment_scope: "production", config_digest: truthHex64, readback_revision: truthHex40, +readback_at: "2026-08-02T00:00:00Z", readback_source: "https://control.example.invalid/readback", operating_state: "normal", }], health_state: "healthy", health: { as_of: "2026-08-01", +status: "healthy", score: 90, components: { performance: 90, risk: 89, decay: null, stability: 88, operations: 91 }, +decision: { code: "human_live_gate", label: "Review", reason: "Evidence ready" }, review: { requested_stage: "live_candidate", evidence_package_id: "evidence-1", validation: { Pass: true }, +risk: {}, kelly_readiness: {}, }, freshness: { status: "fresh", age_seconds: 30 }, source_revision: "https://example.invalid/revision", }, }], errors: [], }; } +function runTruthNormalize(caseId, raw, disposition, expected, inputMutation, schemaProof = disposition === "accept") { truthExpectedIds.push(caseId); const receipt = { case_id: caseId, +group: caseId.split(".")[0], test_path: "tests/strategy_switch_worker_validation.mjs", production_entrypoint: "__test.normalizeStrategyTruthSnapshot(payload, fieldName, now)", +input_mutation: inputMutation, exact_expected: expected, disposition, assertion_result: "FAIL", +schema_target: schemaProof ? "schemas/strategy-truth-dashboard.v1.schema.json" : "NOT_APPLICABLE", schema_result: schemaProof ? "FAIL" : "NOT_APPLICABLE", }; try { +assert.equal(typeof __test.normalizeStrategyTruthSnapshot, "function", "missing production normalizer entrypoint"); let actual; let thrown; try { +actual = __test.normalizeStrategyTruthSnapshot(raw, "strategy truth snapshot", truthNow); } catch (error) { thrown = error; } if (disposition === "reject") { +assert.ok(thrown, "expected whole-payload rejection"); } else { if (thrown) throw thrown; assert.deepEqual(actual, expected); if (schemaProof) { +assert.ok(truthSchema, "missing truth Schema entrypoint"); truthAccepted.push({ case_id: caseId, value: actual }); receipt.schema_result = "PENDING_BATCH_VALIDATION"; } } +receipt.assertion_result = "PASS"; } catch (error) { receipt.failure = String(error?.message || error); } truthReceipts.push(receipt); } +function runTruthProof(caseId, productionEntrypoint, inputMutation, exactExpected, assertion, schemaTarget = "NOT_APPLICABLE") { truthExpectedIds.push(caseId); const receipt = { +case_id: caseId, group: caseId.split(".")[0], test_path: "tests/strategy_switch_worker_validation.mjs", production_entrypoint: productionEntrypoint, input_mutation: inputMutation, +exact_expected: exactExpected, +disposition: caseId === "C_FIXED_POINT.schema_valid_noncanonical_excluded" ? "scope" : "proof", assertion_result: "FAIL", schema_target: schemaTarget, +schema_result: schemaTarget === "NOT_APPLICABLE" ? "NOT_APPLICABLE" : "FAIL", }; try { assertion(); receipt.assertion_result = "PASS"; +if (schemaTarget !== "NOT_APPLICABLE") receipt.schema_result = "PASS"; } catch (error) { receipt.failure = String(error?.message || error); } truthReceipts.push(receipt); } +async function runTruthRoute(caseId, request, env, inputMutation, exactExpected, assertion, disposition = "proof") { truthExpectedIds.push(caseId); const receipt = { case_id: caseId, +group: caseId.split(".")[0], test_path: "tests/strategy_switch_worker_validation.mjs", production_entrypoint: `${request.method} ${new URL(request.url).pathname} -> production Worker route/storage`, +input_mutation: inputMutation, exact_expected: exactExpected, disposition, assertion_result: "FAIL", +schema_target: disposition === "accept" ? "schemas/strategy-truth-dashboard.v1.schema.json" : "NOT_APPLICABLE", schema_result: disposition === "accept" ? "FAIL" : "NOT_APPLICABLE", }; try { +const response = await worker.fetch(request, env); await assertion(response); receipt.assertion_result = "PASS"; +if (disposition === "accept") receipt.schema_result = "PENDING_BATCH_VALIDATION"; } catch (error) { receipt.failure = String(error?.message || error); } truthReceipts.push(receipt); } +runTruthProof( +"W_SHAPE_ENUM.normalizer_export", "__test.normalizeStrategyTruthSnapshot", "read exported production entrypoint", "typeof entrypoint === function", +() => assert.equal(typeof __test.normalizeStrategyTruthSnapshot, "function"), ); const literalTruth = makeTruthBaseline(); runTruthNormalize( +"C_FIXED_POINT.literal_baseline", structuredClone(literalTruth), "accept", literalTruth, "independent already-canonical literal fixture", ); runTruthNormalize( +"C_FIXED_POINT.producer_handoff_output", structuredClone(literalTruth), "accept", literalTruth, "explicit local producer handoff canonical fixture", ); +const numericFields = ["score", "performance", "risk", "decay", "stability", "operations"]; const numericAccept = [ +["missing", undefined, null], +["null", null, null], +["blank", "", null], +["numeric_string", "12.5", 12.5], +["zero", 0, 0], +["hundred", 100, 100], ]; const numericReject = [ +["boolean_false", false], +["boolean_true", true], +["just_below", -0.01], +["just_above", 100.01], +["nan", Number.NaN], +["infinity", Number.POSITIVE_INFINITY], ]; for (const field of numericFields) { for (const [suffix, rawValue, canonicalValue] of numericAccept) { const raw = makeTruthBaseline(); +const expected = makeTruthBaseline(); const rawTarget = field === "score" ? raw.profiles[0].health : raw.profiles[0].health.components; +const expectedTarget = field === "score" ? expected.profiles[0].health : expected.profiles[0].health.components; if (suffix === "missing") delete rawTarget[field]; +else rawTarget[field] = rawValue; expectedTarget[field] = canonicalValue; runTruthNormalize( +`W_NUMERIC.${field}.${suffix}`, raw, "accept", expected, `health ${field}=${suffix === "missing" ? "missing" : String(rawValue)}`, ); } for (const [suffix, rawValue] of numericReject) { +const raw = makeTruthBaseline(); const target = field === "score" ? raw.profiles[0].health : raw.profiles[0].health.components; target[field] = rawValue; +runTruthNormalize(`W_NUMERIC.${field}.${suffix}`, raw, "reject", "whole-payload reject", `health ${field}=${String(rawValue)}`); } } const ageAccept = [ +["missing", undefined, null], +["null", null, null], +["empty", "", null], +["zero", 0, 0], +["max", 315360000, 315360000], +["number_1_49", 1.49, 1], +["number_1_5", 1.5, 2], +["string_1_49", "1.49", 1], +["string_1_5", "1.5", 2], ]; for (const [suffix, rawValue, canonicalValue] of ageAccept) { const raw = makeTruthBaseline(); const expected = makeTruthBaseline(); +if (suffix === "missing") delete raw.profiles[0].health.freshness.age_seconds; else raw.profiles[0].health.freshness.age_seconds = rawValue; +expected.profiles[0].health.freshness.age_seconds = canonicalValue; +runTruthNormalize(`W_NUMERIC.age.${suffix}`, raw, "accept", expected, `age_seconds=${suffix}`); } for (const [suffix, rawValue] of [ +["below_raw_rounds_in", -0.49], +["above_raw_rounds_in", 315360000.49], +["nan", Number.NaN], +["infinity", Number.POSITIVE_INFINITY], ]) { const raw = makeTruthBaseline(); raw.profiles[0].health.freshness.age_seconds = rawValue; +runTruthNormalize(`W_NUMERIC.age.${suffix}`, raw, "reject", "reject before rounding", `age_seconds=${String(rawValue)}`); } +for (const [suffix, count, disposition] of [["0", 0, "accept"], ["12", 12, "accept"], ["13", 13, "reject"]]) { const raw = makeTruthBaseline(); +const entries = Array.from({ length: count }, (_, index) => [`m${String(index).padStart(2, "0")}`, index]); raw.profiles[0].health.review.validation = Object.fromEntries(entries); +const expected = makeTruthBaseline(); expected.profiles[0].health.review.validation = Object.fromEntries(entries); runTruthNormalize( +`W_SCALAR.count.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject before filtering", `validation raw property count=${count}`, ); } +const forbiddenScalarWords = ["cookie", "key", "password", "path", "private", "secret", "token"]; +const forbiddenScalarCases = [["lower", (word) => word], ["mixed", (word) => `${word[0].toUpperCase()}${word.slice(1)}`]]; forbiddenScalarCases.push(["upper", (word) => word.toUpperCase()]); +for (const word of forbiddenScalarWords) { for (const [caseName, transform] of forbiddenScalarCases) { const key = `metric_${transform(word)}`; const raw = makeTruthBaseline(); +raw.profiles[0].health.review.validation = { safe: true, [key]: true }; const expected = makeTruthBaseline(); expected.profiles[0].health.review.validation = { safe: true }; +runTruthNormalize(`W_SCALAR.forbidden.${word}.${caseName}`, raw, "accept", expected, `validation key=${key}`); } } const scalarKeyCases = [ +["allowed_punctuation", "Az_09.-", true], +["invalid_char", "bad/key", false], +["length_0", "", false], +["length_1", "A", true], +["length_48", "x".repeat(48), true], +["length_49", "x".repeat(49), false], ]; for (const [suffix, key, retained] of scalarKeyCases) { const raw = makeTruthBaseline(); raw.profiles[0].health.review.validation = { [key]: true }; +const expected = makeTruthBaseline(); expected.profiles[0].health.review.validation = retained ? { [key]: true } : {}; +runTruthNormalize(`W_SCALAR.key.${suffix}`, raw, "accept", expected, `validation key=${JSON.stringify(key)}`); } { const raw = makeTruthBaseline(); +raw.profiles[0].health.review.validation = { Pass: true, pass: false }; const expected = structuredClone(raw); +runTruthNormalize("W_SCALAR.key.pass_case_pair", raw, "accept", expected, "validation has distinct Pass and pass keys"); } for (const mapName of ["kelly_readiness", "risk", "validation"]) { +const raw = makeTruthBaseline(); raw.profiles[0].health.review[mapName] = { safe: true }; const expected = structuredClone(raw); +runTruthNormalize(`W_SCALAR.map.${mapName}`, raw, "accept", expected, `${mapName}={safe:true}`); } for (const [suffix, entries] of [ +["permutation_a", [["z", 3], ["a", 1], ["m", 2]]], +["permutation_b", [["m", 2], ["z", 3], ["a", 1]]], ]) { const raw = makeTruthBaseline(); raw.profiles[0].health.review.validation = Object.fromEntries(entries); +const expected = makeTruthBaseline(); expected.profiles[0].health.review.validation = { a: 1, m: 2, z: 3 }; +runTruthNormalize(`W_SCALAR.order.${suffix}`, raw, "accept", expected, `input key order=${entries.map(([key]) => key).join(",")}`); } +for (const [suffix, rawValue] of [["array", []], ["missing", undefined], ["nonobject", "x"], ["null", null]]) { const raw = makeTruthBaseline(); +if (suffix === "missing") delete raw.profiles[0].health.review.validation; else raw.profiles[0].health.review.validation = rawValue; const expected = makeTruthBaseline(); +expected.profiles[0].health.review.validation = {}; +runTruthNormalize(`W_SCALAR.shape.${suffix}`, raw, "accept", expected, `validation=${suffix}`); } const scalarValueCases = [ +["array", [], undefined, "accept"], +["boolean_false", false, false, "accept"], +["boolean_true", true, true, "accept"], +["null", null, undefined, "accept"], +["number_above", 1000000.01, undefined, "reject"], +["number_below", -1000000.01, undefined, "reject"], +["number_infinity", Number.POSITIVE_INFINITY, undefined, "reject"], +["number_max", 1000000, 1000000, "accept"], +["number_min", -1000000, -1000000, "accept"], +["number_nan", Number.NaN, undefined, "reject"], +["numeric_string", " 12 ", "12", "accept"], +["object", {}, undefined, "accept"], +["string_1", "x", "x", "accept"], +["string_120", "x".repeat(120), "x".repeat(120), "accept"], +["string_121", "x".repeat(121), undefined, "accept"], +["string_blank", " ", undefined, "accept"], +["string_credential", "secret=synthetic-value", undefined, "accept"], +["string_markup", "", undefined, "accept"], +["string_private_path", "/Users/demo/private", undefined, "accept"], ]; for (const [suffix, rawValue, canonicalValue, disposition] of scalarValueCases) { const raw = makeTruthBaseline(); +raw.profiles[0].health.review.validation = { metric: rawValue }; const expected = makeTruthBaseline(); +expected.profiles[0].health.review.validation = canonicalValue === undefined ? {} : { metric: canonicalValue }; runTruthNormalize( +`W_SCALAR.value.${suffix}`, raw, disposition, disposition === "accept" ? expected : "whole-payload reject", `validation.metric=${suffix}`, ); } const truthEnumDimensions = [ +["catalog_stage", ["research_backtest_only", "shadow_candidate", "live_candidate", "runtime_enabled"]], +["data_status", ["ready", "stale", "unavailable"]], +["deployment_label", ["live", "paper", "off", "research_only", "deployment_unknown"]], +["deployment_scope", ["production", "paper", "research", "disabled"]], +["domain", ["us_equity", "hk_equity", "cn_equity", "crypto"]], +["execution_mode", ["off", "dry_run", "paper", "live"]], +["health_freshness_status", ["fresh", "stale", "unknown"]], +["health_state", ["healthy", "watch", "review", "critical", "unavailable"]], +["health_status", ["healthy", "watch", "review", "critical"]], +["operating_state", ["normal", "watch", "reduced", "quarantined", "retired", "unknown"]], +["platform_id", ["longbridge", "ibkr", "schwab", "firstrade", "qmt", "binance"]], +["provenance_freshness", ["fresh", "stale", "unavailable"]], ]; for (const [field, values] of truthEnumDimensions) { for (const value of [...values, "invalid"]) { +const raw = makeTruthBaseline(); const expected = makeTruthBaseline(); let disposition = value === "invalid" ? "reject" : "accept"; +if (field === "catalog_stage") raw.profiles[0].catalog_stage = expected.profiles[0].catalog_stage = value; +if (field === "domain") raw.profiles[0].domain = expected.profiles[0].domain = value; +if (field === "platform_id") raw.profiles[0].bindings[0].platform_id = expected.profiles[0].bindings[0].platform_id = value; if (field === "deployment_scope") { +raw.profiles[0].bindings[0].deployment_scope = value; expected.profiles[0].bindings[0].deployment_scope = value; } if (field === "operating_state") { +raw.profiles[0].bindings[0].operating_state = value; expected.profiles[0].bindings[0].operating_state = value; } if (field === "execution_mode") { +raw.profiles[0].bindings[0].execution_mode = expected.profiles[0].bindings[0].execution_mode = value; +raw.profiles[0].bindings[0].enabled = expected.profiles[0].bindings[0].enabled = value !== "off"; } if (field === "deployment_label") { +raw.profiles[0].deployment_label = expected.profiles[0].deployment_label = value; raw.summary = { profile_count: 1, live: 0, paper: 0, off: 0, research_only: 0, deployment_unknown: 0 }; +if (value !== "invalid") raw.summary[value] = 1; expected.summary = structuredClone(raw.summary); } if (field === "health_freshness_status") { +raw.profiles[0].health.freshness.status = expected.profiles[0].health.freshness.status = value; } if (field === "health_status") { +raw.profiles[0].health.status = expected.profiles[0].health.status = value; if (value !== "invalid") raw.profiles[0].health_state = expected.profiles[0].health_state = value; } +if (field === "health_state") { raw.profiles[0].health_state = expected.profiles[0].health_state = value; +if (value === "unavailable") raw.profiles[0].health = expected.profiles[0].health = null; +else if (value !== "invalid") raw.profiles[0].health.status = expected.profiles[0].health.status = value; } if (field === "data_status") { raw.data_status = expected.data_status = value; +if (value === "unavailable") { raw.generated_at = expected.generated_at = null; raw.computed_at = expected.computed_at = null; raw.input_provenance = expected.input_provenance = { +sha256: null, source_revision: null, config_digest: null, freshness: "unavailable", }; } } if (field === "provenance_freshness") { +raw.input_provenance.freshness = expected.input_provenance.freshness = value; if (value === "unavailable") { raw.data_status = expected.data_status = "unavailable"; +raw.generated_at = expected.generated_at = null; raw.computed_at = expected.computed_at = null; raw.input_provenance.sha256 = expected.input_provenance.sha256 = null; +raw.input_provenance.source_revision = expected.input_provenance.source_revision = null; raw.input_provenance.config_digest = expected.input_provenance.config_digest = null; } } +runTruthNormalize( +`W_SHAPE_ENUM.enum.${field}.${value}`, raw, disposition, disposition === "accept" ? expected : "whole-payload reject", `${field}=${value}`, ); } } +for (const [suffix, rootValue] of [["array", []], ["empty", {}], ["nonobject", "truth"], ["null", null]]) { +runTruthNormalize(`W_SHAPE_ENUM.root.${suffix}`, rootValue, "reject", "reject non-closed root", `root=${suffix}`); } +for (const [suffix, value] of [["array", []], ["missing", undefined], ["nonobject", "provenance"], ["null", null]]) { const raw = makeTruthBaseline(); +if (suffix === "missing") delete raw.input_provenance; else raw.input_provenance = value; +runTruthNormalize(`W_SHAPE_ENUM.provenance.${suffix}`, raw, "reject", "reject required provenance object", `provenance=${suffix}`); } +for (const [suffix, value] of [["array", []], ["missing", undefined], ["nonobject", "summary"], ["null", null]]) { const raw = makeTruthBaseline(); +if (suffix === "missing") delete raw.summary; else raw.summary = value; +runTruthNormalize(`W_SHAPE_ENUM.summary.${suffix}`, raw, "reject", "reject required summary object", `summary=${suffix}`); } +for (const [suffix, field] of [["profile_count_mismatch", "profile_count"], ["label_count_mismatch", "live"]]) { const raw = makeTruthBaseline(); raw.summary[field] = 0; +runTruthNormalize(`W_SHAPE_ENUM.summary.${suffix}`, raw, "reject", "reject cross-field count mismatch", `summary.${field}=0`); } for (const [collection, cases] of [ +["profiles", [["missing", undefined], ["nonarray", "profiles"], ["null", null]]], +["bindings", [["missing", undefined], ["nonarray", "bindings"], ["null", null]]], ]) { for (const [suffix, value] of cases) { const raw = makeTruthBaseline(); +const target = collection === "profiles" ? raw : raw.profiles[0]; if (suffix === "missing") delete target[collection]; else target[collection] = value; +runTruthNormalize(`W_SHAPE_ENUM.${collection}.${suffix}`, raw, "reject", `reject required ${collection} array`, `${collection}=${suffix}`); } } for (const [kind, collection, values] of [ +["profile_item", "profiles", [["array", []], ["nonobject", "profile"], ["null", null]]], +["binding_item", "bindings", [["array", []], ["nonobject", "binding"], ["null", null]]], ]) { for (const [suffix, value] of values) { const raw = makeTruthBaseline(); +if (collection === "profiles") raw.profiles = [value]; else raw.profiles[0].bindings = [value]; +runTruthNormalize(`W_SHAPE_ENUM.${kind}.${suffix}`, raw, "reject", "reject non-object item", `${collection}[0]=${suffix}`); } } +for (const [caseId, target] of [["profile.missing_key", "domain"], ["binding.missing_key", "platform_id"]]) { const raw = makeTruthBaseline(); +if (caseId.startsWith("profile")) delete raw.profiles[0][target]; else delete raw.profiles[0].bindings[0][target]; +runTruthNormalize(`W_SHAPE_ENUM.${caseId}`, raw, "reject", "reject closed item with missing key", `delete ${target}`); } +for (const nested of ["components", "decision", "review", "freshness"]) { for (const [suffix, value] of [["array", []], ["missing", undefined], ["nonobject", nested], ["null", null]]) { +const raw = makeTruthBaseline(); if (suffix === "missing") delete raw.profiles[0].health[nested]; else raw.profiles[0].health[nested] = value; const expected = makeTruthBaseline(); +if (nested === "components") { expected.profiles[0].health.components = { performance: null, risk: null, decay: null, stability: null, operations: null }; } if (nested === "decision") { +expected.profiles[0].health.decision = { code: "evidence_missing", label: "证据不足,保持研究态", reason: "没有可用的机器检查结果。", }; } if (nested === "review") { +expected.profiles[0].health.review = { requested_stage: null, evidence_package_id: null, validation: {}, risk: {}, kelly_readiness: {}, }; } +if (nested === "freshness") expected.profiles[0].health.freshness = { status: "unknown", age_seconds: null }; +runTruthNormalize(`W_SHAPE_ENUM.${nested}.${suffix}`, raw, "accept", expected, `health.${nested}=${suffix}`); } } const healthShapeCases = [ +["available_array", "healthy", [], "reject"], +["available_missing", "healthy", undefined, "reject"], +["available_nonobject", "healthy", "health", "reject"], +["available_null", "healthy", null, "reject"], +["status_conflict", "healthy", structuredClone(makeTruthBaseline().profiles[0].health), "reject"], +["unavailable_array", "unavailable", [], "reject"], +["unavailable_nonobject", "unavailable", "health", "reject"], +["unavailable_null", "unavailable", null, "accept"], +["unavailable_object", "unavailable", structuredClone(makeTruthBaseline().profiles[0].health), "reject"], ]; healthShapeCases[4][2].status = "watch"; +for (const [suffix, healthState, healthValue, disposition] of healthShapeCases) { const raw = makeTruthBaseline(); raw.profiles[0].health_state = healthState; +if (suffix === "available_missing") delete raw.profiles[0].health; else raw.profiles[0].health = healthValue; const expected = makeTruthBaseline(); +expected.profiles[0].health_state = "unavailable"; expected.profiles[0].health = null; runTruthNormalize( +`W_SHAPE_ENUM.health.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject health iff/status conflict", `health_state=${healthState}; health=${suffix}`, ); } +for (const [suffix, value] of [["missing", undefined], ["nonarray", "errors"], ["null", null]]) { const raw = makeTruthBaseline(); if (suffix === "missing") delete raw.errors; +else raw.errors = value; const expected = makeTruthBaseline(); expected.errors = []; const disposition = suffix === "missing" ? "reject" : "accept"; runTruthNormalize( +`W_SHAPE_ENUM.errors.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject missing required key", `errors=${suffix}`, ); } { const raw = makeTruthBaseline(); +raw.errors = ["duplicate", "duplicate", "safe"]; const expected = makeTruthBaseline(); expected.errors = ["duplicate", "safe"]; +runTruthNormalize("W_SHAPE_ENUM.errors.duplicate", raw, "accept", expected, "duplicate canonical error codes"); } +for (const nested of ["components", "decision", "freshness", "health", "review"]) { const raw = makeTruthBaseline(); if (nested === "health") raw.profiles[0].health.extra = "drop"; +else raw.profiles[0].health[nested].extra = "drop"; const expected = makeTruthBaseline(); +runTruthNormalize(`W_SHAPE_ENUM.extra.${nested}`, raw, "accept", expected, `health.${nested}.extra=drop`); } for (const target of ["top", "profile", "binding"]) { +const raw = makeTruthBaseline(); if (target === "top") raw.extra = "reject"; if (target === "profile") raw.profiles[0].extra = "reject"; +if (target === "binding") raw.profiles[0].bindings[0].extra = "reject"; +runTruthNormalize(`W_SHAPE_ENUM.extra.${target}`, raw, "reject", "reject closed raw shape", `${target}.extra=reject`); } +for (const [suffix, target] of [["profile_case", "profile"], ["binding_case", "binding"]]) { const raw = makeTruthBaseline(); if (target === "profile") { +const duplicate = structuredClone(raw.profiles[0]); duplicate.strategy_profile = raw.profiles[0].strategy_profile.toUpperCase(); raw.profiles.push(duplicate); +raw.summary.profile_count = raw.summary.live = 2; } else { const duplicate = structuredClone(raw.profiles[0].bindings[0]); +duplicate.binding_id = raw.profiles[0].bindings[0].binding_id.toUpperCase(); raw.profiles[0].bindings.push(duplicate); } +runTruthNormalize(`W_SHAPE_ENUM.duplicate.${suffix}`, raw, "reject", "reject duplicate case-normalized ID", `${target} duplicate case`); } for (const [collection, count, disposition] of [ +["bindings", 0, "accept"], +["bindings", 100, "accept"], +["bindings", 101, "reject"], +["profiles", 0, "accept"], +["profiles", 100, "accept"], +["profiles", 101, "reject"], +["errors", 0, "accept"], +["errors", 20, "accept"], +["errors", 21, "accept"], ]) { const raw = makeTruthBaseline(); if (collection === "bindings") { raw.profiles[0].bindings = Array.from({ length: count }, (_, index) => { +const binding = structuredClone(makeTruthBaseline().profiles[0].bindings[0]); binding.binding_id = `binding-${String(index).padStart(3, "0")}`; return binding; }); } +if (collection === "profiles") { raw.profiles = Array.from({ length: count }, (_, index) => { const profile = structuredClone(makeTruthBaseline().profiles[0]); +profile.strategy_profile = `profile-${String(index).padStart(3, "0")}`; return profile; }); raw.summary.profile_count = count; raw.summary.live = count; } +if (collection === "errors") raw.errors = Array.from({ length: count }, (_, index) => `error_${String(index).padStart(2, "0")}`); const expected = structuredClone(raw); +if (collection === "errors" && count === 21) expected.errors = raw.errors.slice(0, 20); runTruthNormalize( +`W_SHAPE_ENUM.count.${collection}.${count === 0 ? "zero" : count}`, raw, disposition, disposition === "accept" ? expected : "reject over maximum collection size", +`${collection} raw count=${count}`, ); } for (const idField of ["binding_id", "strategy_profile"]) { for (const [suffix, rawValue, canonicalValue, disposition] of [ +["invalid_char", "bad/id", null, "reject"], +["length_0", "", null, "reject"], +["length_1", "a", "a", "accept"], +["length_120", "x".repeat(120), "x".repeat(120), "accept"], +["length_121", "x".repeat(121), null, "reject"], +["number", 123, null, "reject"], +["uppercase", "DEMO_ALPHA", "demo_alpha", "accept"], ]) { const raw = makeTruthBaseline(); const expected = makeTruthBaseline(); if (idField === "binding_id") { +raw.profiles[0].bindings[0].binding_id = rawValue; expected.profiles[0].bindings[0].binding_id = canonicalValue; } else { raw.profiles[0].strategy_profile = rawValue; +expected.profiles[0].strategy_profile = canonicalValue; } runTruthNormalize( +`W_SHAPE_ENUM.identity.${idField}.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject invalid identity slug", `${idField}=${suffix}`, ); } } { +const raw = makeTruthBaseline(); const second = structuredClone(raw.profiles[0].bindings[0]); second.binding_id = "a-binding"; +raw.profiles[0].bindings = [raw.profiles[0].bindings[0], second].reverse(); +runTruthNormalize("W_SHAPE_ENUM.order.bindings_preserved", raw, "accept", structuredClone(raw), "two bindings in reversed input order"); } { const raw = makeTruthBaseline(); +const second = structuredClone(raw.profiles[0]); second.strategy_profile = "a-profile"; raw.profiles = [raw.profiles[0], second].reverse(); raw.summary.profile_count = raw.summary.live = 2; +runTruthNormalize("W_SHAPE_ENUM.order.profiles_preserved", raw, "accept", structuredClone(raw), "two profiles in reversed input order"); } const decisionCases = [ +["code_blank", "code", " ", null, "reject"], +["code_invalid_char", "code", "bad/code", null, "reject"], +["code_lower", "code", "review_gate", "review_gate", "accept"], +["code_missing", "code", undefined, "evidence_missing", "accept"], +["code_overlength", "code", "x".repeat(121), null, "reject"], +["code_trim", "code", " review_gate ", "review_gate", "accept"], +["code_upper", "code", "REVIEW_GATE", "review_gate", "accept"], +["label_missing_fallback", "label", undefined, "证据不足,保持研究态", "accept"], +["label_unsafe_fallback", "label", "", "证据不足,保持研究态", "accept"], +["reason_missing_fallback", "reason", undefined, "没有可用的机器检查结果。", "accept"], +["reason_unsafe_fallback", "reason", "", "没有可用的机器检查结果。", "accept"], ]; for (const [suffix, field, rawValue, canonicalValue, disposition] of decisionCases) { +const raw = makeTruthBaseline(); const expected = makeTruthBaseline(); if (rawValue === undefined) delete raw.profiles[0].health.decision[field]; +else raw.profiles[0].health.decision[field] = rawValue; expected.profiles[0].health.decision[field] = canonicalValue; runTruthNormalize( +`W_TEXT_DECISION.decision.${suffix}`, raw, disposition, disposition === "accept" ? expected : "whole-payload reject", `decision.${field}=${suffix}`, ); } +for (const [suffix, rawValue] of [["object_missing", undefined], ["object_null", null]]) { const raw = makeTruthBaseline(); +if (suffix === "object_missing") delete raw.profiles[0].health.decision; else raw.profiles[0].health.decision = rawValue; const expected = makeTruthBaseline(); +expected.profiles[0].health.decision = { code: "evidence_missing", label: "证据不足,保持研究态", reason: "没有可用的机器检查结果。", }; +runTruthNormalize(`W_TEXT_DECISION.decision.${suffix}`, raw, "accept", expected, `decision=${suffix}`); } +const credentialAssignments = ["api_key", "cookie", "password", "private_key", "secret", "token"]; const shapedCanaries = [ +["gho", `gho_${"x".repeat(36)}`], +["ghp", `ghp_${"x".repeat(36)}`], +["ghr", `ghr_${"x".repeat(36)}`], +["ghs", `ghs_${"x".repeat(36)}`], +["ghu", `ghu_${"x".repeat(36)}`], +["jwt", `eyJ${"x".repeat(36)}.${"y".repeat(20)}.${"z".repeat(20)}`], +["sk", `sk-${"x".repeat(40)}`], ]; const strictSourceCases = [ +["bearer", `Bearer ${"x".repeat(24)}`, null, "reject"], +["blank", " ", null, "reject"], +["local", "local-qrs-readback", "local-qrs-readback", "accept"], +["markup", "", null, "reject"], +["overlength", "x".repeat(121), null, "reject"], +["posix_home", "FiLe:///home/demo/private", null, "reject"], +["posix_users", "/Users/demo/private", null, "reject"], +["root", "/", null, "reject"], +["safe_url", "https://control.example.invalid/readback", "https://control.example.invalid/readback", "accept"], +["credential_url.malformed", "https://synthetic-user:synthetic-pass@control.example.invalid:bad", null, "reject"], +["credential_url.signed_query", "https://control.example.invalid/readback?X-Amz-Signature=synthetic-signature", null, "reject"], +["credential_url.userinfo", "https://synthetic-user:synthetic-pass@control.example.invalid/readback", null, "reject"], +["trim", " local-qrs-readback ", "local-qrs-readback", "accept"], +["windows", "C:\\private\\file", null, "reject"], ]; +for (const keyword of credentialAssignments) strictSourceCases.push([`assignment.${keyword}`, `${keyword}=synthetic-value`, null, "reject"]); +for (const [name, canary] of shapedCanaries) strictSourceCases.push([`canary.${name}`, canary, null, "reject"]); +for (const [suffix, rawValue, canonicalValue, disposition] of strictSourceCases) { const raw = makeTruthBaseline(); raw.profiles[0].bindings[0].readback_source = rawValue; +const expected = makeTruthBaseline(); expected.profiles[0].bindings[0].readback_source = canonicalValue; runTruthNormalize( +`W_TEXT_DECISION.readback_source.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject strict unsafe readback_source without echo", `binding.readback_source=${suffix}`, +); } const nullableSourceCases = [ +["bearer", `Bearer ${"x".repeat(24)}`, null], +["blank", " ", null], +["length_1", "x", "x"], +["length_120", "x".repeat(120), "x".repeat(120)], +["length_121", "x".repeat(121), null], +["markup", "", null], +["posix_home", "/home/demo/private", null], +["posix_users", "/Users/demo/private", null], +["root", "/", null], +["safe", "safe", "safe"], +["safe_url", "https://example.invalid/revision", "https://example.invalid/revision"], +["trim", " safe ", "safe"], +["windows", "C:\\private\\file", null], ]; for (const keyword of credentialAssignments) nullableSourceCases.push([`assignment.${keyword}`, `${keyword}=synthetic-value`, null]); +for (const [name, canary] of shapedCanaries) nullableSourceCases.push([`canary.${name}`, canary, null]); for (const [suffix, rawValue, canonicalValue] of nullableSourceCases) { +const raw = makeTruthBaseline(); raw.profiles[0].health.source_revision = rawValue; const expected = makeTruthBaseline(); expected.profiles[0].health.source_revision = canonicalValue; +runTruthNormalize( +`W_TEXT_DECISION.safe_text.source_revision.${suffix}`, raw, "accept", expected, `health.source_revision=${suffix}`, ); } for (const [suffix, rawValue] of [ +["credential_url.malformed", "https://synthetic-user:synthetic-pass@example.invalid:bad"], +["credential_url.signed_query", "https://example.invalid/revision?X-Amz-Signature=synthetic-signature"], +["credential_url.userinfo", "https://synthetic-user:synthetic-pass@example.invalid/revision"], ]) { const raw = makeTruthBaseline(); +raw.profiles[0].health.source_revision = rawValue; runTruthNormalize( +`W_TEXT_DECISION.source_revision.${suffix}`, raw, "reject", "reject unsafe URL source_revision without echo", `health.source_revision=${suffix}`, ); } for (const [field, maximum, target] of [ +["as_of", 64, "health"], +["evidence_package_id", 120, "review"], +["label", 120, "decision"], +["reason", 240, "decision"], +["requested_stage", 120, "review"], ]) { for (const [suffix, length] of [["at_limit", maximum], ["over_limit", maximum + 1]]) { const raw = makeTruthBaseline(); +const expected = makeTruthBaseline(); const rawTarget = target === "health" ? raw.profiles[0].health : raw.profiles[0].health[target]; +const expectedTarget = target === "health" ? expected.profiles[0].health : expected.profiles[0].health[target]; rawTarget[field] = "x".repeat(length); +if (suffix === "at_limit") expectedTarget[field] = rawTarget[field]; else if (field === "label") expectedTarget[field] = "证据不足,保持研究态"; +else if (field === "reason") expectedTarget[field] = "没有可用的机器检查结果。"; else expectedTarget[field] = null; runTruthNormalize( +`W_TEXT_DECISION.safe_text.${field}.${suffix}`, raw, "accept", expected, `${target}.${field} length=${length}`, ); } } for (const [kind, field] of [ +["revision.binding.readback_revision", "readback_revision"], +["revision.binding.strategy_revision", "strategy_revision"], ]) { for (const [suffix, rawValue, disposition] of [ +["lower_exact", truthHex40, "accept"], +["nonhex", `${"a".repeat(39)}g`, "reject"], +["uppercase", "A".repeat(40), "reject"], +["wrong_length", "a".repeat(39), "reject"], ]) { const raw = makeTruthBaseline(); raw.profiles[0].bindings[0][field] = rawValue; const expected = structuredClone(raw); runTruthNormalize( +`W_TIME_IDENTITY.${kind}.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject invalid lowercase 40-hex revision", `${field}=${suffix}`, ); } } +for (const [suffix, rawValue, disposition] of [ +["lower_exact", truthHex40, "accept"], +["nonhex", `${"a".repeat(39)}g`, "reject"], +["uppercase", "A".repeat(40), "reject"], +["wrong_length", "a".repeat(39), "reject"], ]) { const raw = makeTruthBaseline(); raw.input_provenance.source_revision = rawValue; const expected = structuredClone(raw); runTruthNormalize( +`W_TIME_IDENTITY.revision.provenance.source_revision.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject invalid lowercase 40-hex revision", +`input_provenance.source_revision=${suffix}`, ); } for (const [kind, target] of [ +["digest.binding.config_digest", "binding"], +["digest.provenance.config_digest", "provenance_config"], +["digest.provenance.sha256", "provenance_sha"], ]) { for (const [suffix, rawValue, disposition] of [ +["lower_exact", truthHex64, "accept"], +["nonhex", `${"b".repeat(63)}g`, "reject"], +["uppercase", "B".repeat(64), "reject"], +["wrong_length", "b".repeat(63), "reject"], ]) { const raw = makeTruthBaseline(); if (target === "binding") raw.profiles[0].bindings[0].config_digest = rawValue; +if (target === "provenance_config") raw.input_provenance.config_digest = rawValue; if (target === "provenance_sha") raw.input_provenance.sha256 = rawValue; +const expected = structuredClone(raw); runTruthNormalize( +`W_TIME_IDENTITY.${kind}.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject invalid lowercase 64-hex digest", `${kind}=${suffix}`, ); } } +const generatedTimestampCases = [ +["fraction_1", "2026-08-02T00:00:00.1Z", "2026-08-02T00:00:00.1Z", "accept"], +["fraction_9", "2026-08-02T00:00:00.123456789Z", "2026-08-02T00:00:00.123456789Z", "accept"], +["invalid_calendar", "2026-02-30T00:00:00Z", null, "reject"], +["invalid_hour", "2026-08-02T24:00:00Z", null, "reject"], +["invalid_minute", "2026-08-02T00:60:00Z", null, "reject"], +["invalid_offset", "2026-08-02T00:00:00+24:00", null, "reject"], +["leap_day", "2024-02-29T00:00:00Z", "2024-02-29T00:00:00Z", "accept"], +["leap_second", "2026-08-02T00:00:60Z", null, "reject"], +["no_zone", "2026-08-02T00:00:00", null, "reject"], +["offset", "2026-08-02T08:00:00+08:00", "2026-08-02T08:00:00+08:00", "accept"], +["plus_5m", "2026-08-02T00:05:00Z", "2026-08-02T00:05:00Z", "accept"], +["plus_5m_1ms", "2026-08-02T00:05:00.001Z", null, "reject"], +["trim", " 2026-08-02T00:00:00Z ", "2026-08-02T00:00:00Z", "accept"], +["utc", "2026-08-02T00:00:00Z", "2026-08-02T00:00:00Z", "accept"], ]; for (const [suffix, rawValue, canonicalValue, disposition] of generatedTimestampCases) { +const raw = makeTruthBaseline(); raw.generated_at = rawValue; const expected = makeTruthBaseline(); expected.generated_at = canonicalValue; runTruthNormalize( +`W_TIME_IDENTITY.timestamp.generated_at.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject invalid or out-of-window timestamp", `generated_at=${rawValue}`, ); } +for (const [suffix, rawValue, disposition] of [ +["plus_5m", "2026-08-02T00:05:00Z", "accept"], +["plus_5m_1ms", "2026-08-02T00:05:00.001Z", "reject"], ]) { const raw = makeTruthBaseline(); raw.computed_at = rawValue; const expected = structuredClone(raw); runTruthNormalize( +`W_TIME_IDENTITY.timestamp.computed_at.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject future timestamp beyond 5m", `computed_at=${rawValue}`, ); } +for (const [suffix, rawValue, disposition] of [ +["later_1ms", "2026-08-02T00:05:00.001Z", "reject"], +["minus_7d", "2026-07-26T00:00:00Z", "accept"], +["older_1ms", "2026-07-25T23:59:59.999Z", "reject"], +["plus_5m", "2026-08-02T00:05:00Z", "accept"], ]) { const raw = makeTruthBaseline(); raw.profiles[0].bindings[0].readback_at = rawValue; const expected = structuredClone(raw); +runTruthNormalize( +`W_TIME_IDENTITY.timestamp.readback_at.${suffix}`, raw, disposition, disposition === "accept" ? expected : "reject readback outside inclusive window", `readback_at=${rawValue}`, ); } +for (const dataStatus of ["ready", "stale"]) { for (const [suffix, disposition] of [ +["computed_at_null", "reject"], +["generated_at_null", "reject"], +["provenance_config_digest_null", "reject"], +["provenance_fresh", "accept"], +["provenance_sha256_null", "reject"], +["provenance_source_revision_null", "reject"], +["provenance_stale", "accept"], +["provenance_unavailable", "reject"], ]) { const raw = makeTruthBaseline(); raw.data_status = dataStatus; if (suffix === "computed_at_null") raw.computed_at = null; +if (suffix === "generated_at_null") raw.generated_at = null; if (suffix === "provenance_config_digest_null") raw.input_provenance.config_digest = null; +if (suffix === "provenance_sha256_null") raw.input_provenance.sha256 = null; if (suffix === "provenance_source_revision_null") raw.input_provenance.source_revision = null; +if (suffix === "provenance_fresh") raw.input_provenance.freshness = "fresh"; if (suffix === "provenance_stale") raw.input_provenance.freshness = "stale"; +if (suffix === "provenance_unavailable") raw.input_provenance.freshness = "unavailable"; runTruthNormalize( +`W_TIME_IDENTITY.nullability.${dataStatus}.${suffix}`, raw, disposition, disposition === "accept" ? structuredClone(raw) : "reject conditional nullability conflict", +`data_status=${dataStatus}; ${suffix}`, ); } } for (const [suffix, disposition] of [ +["all_null", "accept"], +["computed_at_nonnull", "reject"], +["generated_at_nonnull", "reject"], +["provenance_config_digest_nonnull", "reject"], +["provenance_fresh", "reject"], +["provenance_sha256_nonnull", "reject"], +["provenance_source_revision_nonnull", "reject"], +["provenance_stale", "reject"], ]) { const raw = makeTruthBaseline(); raw.data_status = "unavailable"; raw.generated_at = null; raw.computed_at = null; +raw.input_provenance = { sha256: null, source_revision: null, config_digest: null, freshness: "unavailable" }; if (suffix === "computed_at_nonnull") raw.computed_at = "2026-08-02T00:00:00Z"; +if (suffix === "generated_at_nonnull") raw.generated_at = "2026-08-02T00:00:00Z"; if (suffix === "provenance_config_digest_nonnull") raw.input_provenance.config_digest = truthHex64; +if (suffix === "provenance_sha256_nonnull") raw.input_provenance.sha256 = truthHex64; if (suffix === "provenance_source_revision_nonnull") raw.input_provenance.source_revision = truthHex40; +if (suffix === "provenance_fresh") raw.input_provenance.freshness = "fresh"; if (suffix === "provenance_stale") raw.input_provenance.freshness = "stale"; runTruthNormalize( +`W_TIME_IDENTITY.nullability.unavailable.${suffix}`, raw, disposition, disposition === "accept" ? structuredClone(raw) : "reject unavailable nullability conflict", +`data_status=unavailable; ${suffix}`, ); } const crossCases = [ +["health.available_when_data_unavailable", "accept"], +["health.unavailable_when_data_ready", "accept"], +["mode.enabled_false_live", "reject"], +["mode.enabled_true_off", "reject"], +["provenance_binding.distinct_digest_unknown_label", "accept"], +["provenance_binding.distinct_revision_unknown_label", "accept"], +["provenance_binding.equal_digest", "accept"], +["provenance_binding.equal_revision", "accept"], ]; for (const [suffix, disposition] of crossCases) { const raw = makeTruthBaseline(); +if (suffix === "health.available_when_data_unavailable") { raw.data_status = "unavailable"; raw.generated_at = raw.computed_at = null; +raw.input_provenance = { sha256: null, source_revision: null, config_digest: null, freshness: "unavailable" }; } if (suffix === "health.unavailable_when_data_ready") { +raw.profiles[0].health_state = "unavailable"; raw.profiles[0].health = null; } if (suffix === "mode.enabled_false_live") raw.profiles[0].bindings[0].enabled = false; +if (suffix === "mode.enabled_true_off") raw.profiles[0].bindings[0].execution_mode = "off"; if (suffix.includes("unknown_label")) { raw.profiles[0].deployment_label = "deployment_unknown"; +raw.summary.live = 0; raw.summary.deployment_unknown = 1; } if (suffix.includes("distinct_digest")) raw.profiles[0].bindings[0].config_digest = "c".repeat(64); +if (suffix.includes("distinct_revision")) raw.profiles[0].bindings[0].strategy_revision = "c".repeat(40); +if (suffix.endsWith("equal_digest")) raw.profiles[0].bindings[0].config_digest = raw.input_provenance.config_digest; +if (suffix.endsWith("equal_revision")) raw.profiles[0].bindings[0].strategy_revision = raw.input_provenance.source_revision; runTruthNormalize( +`W_TIME_IDENTITY.cross.${suffix}`, raw, disposition, disposition === "accept" ? structuredClone(raw) : "reject enabled/execution_mode conflict", suffix, ); } const truthStore = new Map(); +const truthKv = { async get(key) { return truthStore.get(key) || null; }, async put(key, value) { truthStore.set(key, value); }, }; const truthToken = ["truth", "sync", "value"].join("-"); +const truthEnv = { ...healthEnv, STRATEGY_SWITCH_CONFIG: truthKv, STRATEGY_TRUTH_SYNC_TOKEN: truthToken, STRATEGY_TRUTH_STALE_TTL_SECONDS: "300", }; +const truthSession = await __test.makeSession("health-user", [], truthEnv); const truthHeaders = { Cookie: `qsl_switch_session=${truthSession}` }; const routeTruth = makeTruthBaseline(); +const routeNow = new Date(); routeTruth.generated_at = routeNow.toISOString(); routeTruth.computed_at = routeTruth.generated_at; +routeTruth.profiles[0].bindings[0].readback_at = routeTruth.generated_at; const truthPostRequest = (payload) => new Request("https://switch.example/api/internal/sync-strategy-truth", { +method: "POST", headers: { Authorization: `Bearer ${truthToken}`, "Content-Type": "application/json" }, body: JSON.stringify(payload), }); +function makeTruthTransportEnvelope(profileCount, bindingsPerProfile) { const payload = structuredClone(routeTruth); +payload.profiles = Array.from({ length: profileCount }, (_, profileIndex) => { const profile = structuredClone(routeTruth.profiles[0]); +profile.strategy_profile = `profile-${String(profileIndex).padStart(3, "0")}`; +profile.bindings = Array.from({ length: bindingsPerProfile }, (_, bindingIndex) => { const binding = structuredClone(routeTruth.profiles[0].bindings[0]); +binding.binding_id = `binding-${String(profileIndex).padStart(3, "0")}-${String(bindingIndex).padStart(3, "0")}`; return binding; }); return profile; }); +payload.summary.profile_count = profileCount; payload.summary.live = profileCount; return payload; } +function truthSchemaResults(values) { const probe = spawnSync("python3", ["-c", ["import json,sys", "from jsonschema import Draft202012Validator", +"payload=json.load(sys.stdin)", "validator=Draft202012Validator(payload['schema'])", "print(json.dumps([validator.is_valid(value) for value in payload['values']]))", +].join("; ")], { input: JSON.stringify({ schema: truthSchema, values }), encoding: "utf8" }); assert.equal(probe.status, 0, probe.stderr); return JSON.parse(probe.stdout); } +const truthGetRequest = () => new Request("https://switch.example/api/strategy-truth", { headers: truthHeaders }); await runTruthRoute( +"R_STORAGE.post.baseline", truthPostRequest(routeTruth), truthEnv, "authenticated canonical truth POST", "HTTP 200 metadata-only response; normalized canonical KV Schema PASS", +async (response) => { assert.equal(response.status, 200); const body = await response.json(); assert.deepEqual(Object.keys(body).sort(), ["ok", "profile_count", "schema_version"]); +const stored = JSON.parse(truthStore.get("strategy_truth_snapshot")); +truthAccepted.push({ case_id: "R_STORAGE.post.baseline", value: stored }); }, "accept", ); await runTruthRoute( +"C_FIXED_POINT.post_written_output", truthPostRequest(routeTruth), truthEnv, "POST normalized object then read exact truth KV bytes", "stored object re-normalizes deep-equal", +async (response) => { assert.equal(response.status, 200); const stored = JSON.parse(truthStore.get("strategy_truth_snapshot")); +const renormalized = __test.normalizeStrategyTruthSnapshot(stored, "stored truth", Date.now()); assert.deepEqual(renormalized, stored); +truthAccepted.push({ case_id: "C_FIXED_POINT.post_written_output", value: stored }); }, "accept", ); runTruthProof( +"R_STORAGE.kv.normalized_only", "POST /api/internal/sync-strategy-truth -> strategy_truth_snapshot KV", "raw route fixture contains detached nested objects", +"KV bytes equal production-normalized canonical object and omit raw-only values", () => { const stored = JSON.parse(truthStore.get("strategy_truth_snapshot")); +const canonical = __test.normalizeStrategyTruthSnapshot(routeTruth, "route truth", Date.now()); assert.deepEqual(stored, canonical); +assert.notEqual(stored.profiles[0], routeTruth.profiles[0]); }, ); await runTruthRoute( +"R_STORAGE.get.immediate_deep_equal", truthGetRequest(), truthEnv, "authenticated immediate GET after accepted POST", "GET body deep-equals producer-written canonical KV", +async (response) => assert.deepEqual(await response.json(), JSON.parse(truthStore.get("strategy_truth_snapshot"))), ); const rejectedRouteTruth = structuredClone(routeTruth); +const rejectedRouteCanary = "file:///Users/synthetic/private/rejected-post-canary"; rejectedRouteTruth.profiles[0].bindings[0].readback_source = rejectedRouteCanary; +const beforeRejectedPost = truthStore.get("strategy_truth_snapshot"); const beforeRejectedAudit = truthStore.get("audit_log"); await runTruthRoute( +"R_STORAGE.post.reject_no_write", truthPostRequest(rejectedRouteTruth), truthEnv, "strict readback_source private-path canary", "HTTP 400; prior KV byte-identical; error/audit omit canary", +async (response) => { assert.equal(response.status, 400); assert.equal(truthStore.get("strategy_truth_snapshot"), beforeRejectedPost); +assert.equal(truthStore.get("audit_log"), beforeRejectedAudit); assert.equal((await response.text()).includes(rejectedRouteCanary), false); }, "reject", ); +const credentialRouteTruth = structuredClone(routeTruth); +const credentialRouteCanary = "https://synthetic-user:synthetic-pass@control.example.invalid/readback"; +credentialRouteTruth.profiles[0].bindings[0].readback_source = credentialRouteCanary; +await runTruthRoute( +"R_STORAGE.post.reject_credential_url_no_write", truthPostRequest(credentialRouteTruth), truthEnv, "credential-bearing readback_source URL", +"HTTP 400; prior KV/audit byte-identical; response and persisted surfaces omit canary", async (response) => { +const responseBytes = await response.text(); const getBytes = await (await worker.fetch(truthGetRequest(), truthEnv)).text(); +assert.equal(response.status, 400); assert.equal(truthStore.get("strategy_truth_snapshot"), beforeRejectedPost); +assert.equal(truthStore.get("audit_log"), beforeRejectedAudit); +for (const bytes of [responseBytes, truthStore.get("strategy_truth_snapshot") || "", truthStore.get("audit_log") || "", getBytes]) { +assert.equal(bytes.includes(credentialRouteCanary), false); } }, "reject", ); +truthStore.set("strategy_truth_snapshot", beforeRejectedPost); if (beforeRejectedAudit === undefined) truthStore.delete("audit_log"); +else truthStore.set("audit_log", beforeRejectedAudit); +for (const [caseId, mutation, mutate] of [ +["R_STORAGE.post.reject_malformed_credential_url_no_write", "malformed credential-bearing readback_source URL", (raw) => { +raw.profiles[0].bindings[0].readback_source = "https://synthetic-user:synthetic-pass@control.example.invalid:bad"; }], +["R_STORAGE.post.reject_health_source_credential_url_no_write", "credential-bearing health.source_revision URL", (raw) => { +raw.profiles[0].health.source_revision = "https://synthetic-user:synthetic-pass@example.invalid/revision"; }], +["R_STORAGE.post.reject_boolean_score_no_write", "boolean health.score=false", (raw) => { raw.profiles[0].health.score = false; }], +["R_STORAGE.post.reject_boolean_component_no_write", "boolean health.components.risk=true", (raw) => { raw.profiles[0].health.components.risk = true; }], +]) { const raw = structuredClone(routeTruth); mutate(raw); const canary = JSON.stringify(raw); const priorKv = truthStore.get("strategy_truth_snapshot"); +const priorAudit = truthStore.get("audit_log"); await runTruthRoute(caseId, truthPostRequest(raw), truthEnv, mutation, +"HTTP 400; prior KV/audit byte-identical; generic response does not echo input", async (response) => { assert.equal(response.status, 400); +assert.equal(truthStore.get("strategy_truth_snapshot"), priorKv); assert.equal(truthStore.get("audit_log"), priorAudit); +assert.equal((await response.text()).includes(canary), false); }, "reject", ); } +{ const raw = structuredClone(routeTruth); raw.profiles[0].health.review.requested_stage = "x".repeat(120); const priorAudit = truthStore.get("audit_log"); await runTruthRoute( +"R_STORAGE.post.requested_stage_length_120", truthPostRequest(raw), truthEnv, "schema-valid requested_stage length=120", "HTTP 200; stored requested_stage preserved exactly", +async (response) => { assert.equal(response.status, 200); const stored = JSON.parse(truthStore.get("strategy_truth_snapshot")); +assert.equal(stored.profiles[0].health.review.requested_stage, "x".repeat(120)); truthAccepted.push({ case_id: "R_STORAGE.post.requested_stage_length_120", value: stored }); }, "accept", ); +truthStore.set("strategy_truth_snapshot", beforeRejectedPost); if (priorAudit === undefined) truthStore.delete("audit_log"); else truthStore.set("audit_log", priorAudit); } +const transportMaxima = [[1, 100], [2, 100], [3, 80], [4, 80], [5, 48], [8, 48], [9, 26], [16, 26], [17, 14], [26, 6], [32, 14], [33, 7], [64, 7], [65, 3], [100, 3]]; +const transportOverBounds = [[3, 81], [5, 49], [9, 27], [17, 15], [33, 8], [65, 4], [100, 7]]; +runTruthProof( +"C_FIXED_POINT.schema_transport_envelope", "Draft202012Validator(strategy-truth-dashboard.v1.schema.json) + TextEncoder(JSON.stringify)", +"piecewise profile/binding maxima including current 26x6 catalog envelope", "every schema-valid tier maximum is compactly <=256KiB; every next aggregate boundary is Schema-invalid", +() => { const maxima = transportMaxima.map(([profiles, bindings]) => makeTruthTransportEnvelope(profiles, bindings)); +const overBounds = transportOverBounds.map(([profiles, bindings]) => makeTruthTransportEnvelope(profiles, bindings)); +assert.deepEqual(truthSchemaResults(maxima), maxima.map(() => true)); assert.deepEqual(truthSchemaResults(overBounds), overBounds.map(() => false)); +for (const value of maxima) assert.ok(new TextEncoder().encode(JSON.stringify(value)).byteLength <= 256 * 1024); }, "schemas/strategy-truth-dashboard.v1.schema.json", ); +{ const maximum = makeTruthTransportEnvelope(64, 7); const bytes = JSON.stringify(maximum); const priorAudit = truthStore.get("audit_log"); await runTruthRoute( +"R_STORAGE.post.transport_maximum", truthPostRequest(maximum), truthEnv, "schema transport tier maximum 64 profiles x 7 bindings", +"compact body <=256KiB; Schema PASS; route HTTP 200 and complete normalized KV", async (response) => { assert.ok(new TextEncoder().encode(bytes).byteLength <= 256 * 1024); +assert.equal(truthSchemaResults([maximum])[0], true); assert.equal(response.status, 200); const stored = JSON.parse(truthStore.get("strategy_truth_snapshot")); +assert.equal(stored.profiles.length, 64); assert.ok(stored.profiles.every((profile) => profile.bindings.length === 7)); +truthAccepted.push({ case_id: "R_STORAGE.post.transport_maximum", value: stored }); }, "accept", ); +truthStore.set("strategy_truth_snapshot", beforeRejectedPost); if (priorAudit === undefined) truthStore.delete("audit_log"); else truthStore.set("audit_log", priorAudit); } +{ const oversized = makeTruthTransportEnvelope(100, 7); const priorKv = truthStore.get("strategy_truth_snapshot"); const priorAudit = truthStore.get("audit_log"); await runTruthRoute( +"R_STORAGE.post.schema_transport_mismatch", truthPostRequest(oversized), truthEnv, "100 profiles x 7 bindings compact body exceeds fixed 256KiB route cap", +"Schema reject; route HTTP 413; prior KV/audit byte-identical", async (response) => { assert.ok(new TextEncoder().encode(JSON.stringify(oversized)).byteLength > 256 * 1024); +assert.equal(truthSchemaResults([oversized])[0], false); assert.equal(response.status, 413); assert.equal(truthStore.get("strategy_truth_snapshot"), priorKv); +assert.equal(truthStore.get("audit_log"), priorAudit); }, ); } +const savedTruthBytes = truthStore.get("strategy_truth_snapshot") || JSON.stringify(routeTruth); +truthStore.delete("strategy_truth_snapshot"); await runTruthRoute( +"R_STORAGE.get.missing_kv", truthGetRequest(), truthEnv, "delete strategy_truth_snapshot KV", "HTTP 200 canonical unavailable payload", async (response) => { +assert.equal(response.status, 200); const body = await response.json(); assert.equal(body.data_status, "unavailable"); +truthAccepted.push({ case_id: "R_STORAGE.get.missing_kv", value: body }); }, "accept", ); truthStore.set("strategy_truth_snapshot", savedTruthBytes); const corruptStorageCases = [ +["corrupt_cross_field", "health/mode/count conflict", (value) => { value.profiles[0].health.status = "watch"; }], +["corrupt_expired_readback", "readback older than seven days", (value) => { value.profiles[0].bindings[0].readback_at = new Date(Date.now() - 7 * 86400000 - 1).toISOString(); }], +["corrupt_extra", "closed top extra", (value) => { value.extra = "raw-extra"; }], +["corrupt_private_path", "binding private path canary", (value) => { value.profiles[0].bindings[0].readback_source = "file:///home/synthetic/private/corrupt-get-canary"; }], +["corrupt_range", "score above 100", (value) => { value.profiles[0].health.score = 100.01; }], +["corrupt_type", "component object type", (value) => { value.profiles[0].health.components.risk = {}; }], ]; for (const [suffix, mutation, mutate] of corruptStorageCases) { +const corrupt = JSON.parse(savedTruthBytes); mutate(corrupt); truthStore.set("strategy_truth_snapshot", JSON.stringify(corrupt)); await runTruthRoute( +`R_STORAGE.get.${suffix}`, truthGetRequest(), truthEnv, mutation, "fail-closed canonical unavailable; no partial raw return", async (response) => { const body = await response.json(); +assert.equal(body.data_status, "unavailable"); assert.equal(JSON.stringify(body).includes("synthetic/private"), false); }, "reject", ); } { const corrupt = JSON.parse(savedTruthBytes); +const unsafe = "/Users/synthetic/private/nullable-source"; corrupt.profiles[0].health.source_revision = unsafe; truthStore.set("strategy_truth_snapshot", JSON.stringify(corrupt)); +await runTruthRoute( +"R_STORAGE.get.corrupt_nullable_unsafe_text", truthGetRequest(), truthEnv, "stored nullable health.source_revision private path", +"re-normalize source_revision to null; return otherwise canonical; no echo", async (response) => { const body = await response.json(); +assert.equal(body.profiles[0].health.source_revision, null); assert.equal(JSON.stringify(body).includes(unsafe), false); +truthAccepted.push({ case_id: "R_STORAGE.get.corrupt_nullable_unsafe_text", value: body }); }, "accept", ); } const realDateNow = Date.now; for (const [suffix, ageMs, expectedStatus] of [ +["exact", 300000, "ready"], +["just_after", 300001, "stale"], +["just_before", 299999, "ready"], ]) { const stored = structuredClone(routeTruth); stored.generated_at = stored.computed_at = new Date(truthNow - ageMs).toISOString(); +stored.profiles[0].bindings[0].readback_at = new Date(truthNow).toISOString(); const bytes = JSON.stringify(stored); truthStore.set("strategy_truth_snapshot", bytes); +Date.now = () => truthNow; await runTruthRoute( +`R_STORAGE.ttl.${suffix}`, truthGetRequest(), truthEnv, `stored ready age=${ageMs}ms with ttl=300s`, `response data_status=${expectedStatus}; KV byte-identical ready`, async (response) => { +const body = await response.json(); assert.equal(body.data_status, expectedStatus); assert.equal(truthStore.get("strategy_truth_snapshot"), bytes); +truthAccepted.push({ case_id: `R_STORAGE.ttl.${suffix}`, value: body }); }, "accept", ); Date.now = realDateNow; } { const stored = structuredClone(routeTruth); +stored.generated_at = stored.computed_at = new Date(truthNow - 300001).toISOString(); stored.profiles[0].bindings[0].readback_at = new Date(truthNow).toISOString(); +const bytes = JSON.stringify(stored); truthStore.set("strategy_truth_snapshot", bytes); Date.now = () => truthNow; await runTruthRoute( +"R_STORAGE.ttl.response_copy_only", truthGetRequest(), truthEnv, "stored ready age=ttl+1ms", "response copy stale; stored KV remains byte-identical ready", async (response) => { +assert.equal((await response.json()).data_status, "stale"); assert.equal(JSON.parse(truthStore.get("strategy_truth_snapshot")).data_status, "ready"); +assert.equal(truthStore.get("strategy_truth_snapshot"), bytes); const bounded = structuredClone(routeTruth); +bounded.generated_at = bounded.computed_at = new Date(truthNow - 10800000).toISOString(); bounded.profiles[0].bindings[0].readback_at = new Date(truthNow).toISOString(); +for (const [configured, expected] of [["604800", "ready"], ["604801", "stale"], ["Infinity", "stale"], ["invalid", "stale"], ["-1", "stale"], ["0", "stale"]]) { +truthStore.set("strategy_truth_snapshot", JSON.stringify(bounded)); +const ttlResponse = await worker.fetch(truthGetRequest(), { ...truthEnv, STRATEGY_TRUTH_STALE_TTL_SECONDS: configured }); const ttlBody = await ttlResponse.json(); +assert.equal(ttlBody.data_status, expected, `truth TTL ${configured}`); } for (const [ageMs, expected] of [[604800000, "ready"], [604800001, "unavailable"]]) { +const ordered = structuredClone(routeTruth); ordered.generated_at = ordered.computed_at = ordered.profiles[0].bindings[0].readback_at = new Date(truthNow - ageMs).toISOString(); +truthStore.set("strategy_truth_snapshot", JSON.stringify(ordered)); +const orderedResponse = await worker.fetch(truthGetRequest(), { ...truthEnv, STRATEGY_TRUTH_STALE_TTL_SECONDS: "604800" }); const orderedBody = await orderedResponse.json(); +assert.equal(orderedBody.data_status, expected, `truth readback ordering ${ageMs}`); } truthStore.set("strategy_truth_snapshot", savedTruthBytes); }, ); Date.now = realDateNow; } +{ const stored = structuredClone(routeTruth); stored.generated_at = stored.computed_at = new Date(truthNow).toISOString(); +stored.profiles[0].bindings[0].readback_at = new Date(truthNow - 300001).toISOString(); const bytes = JSON.stringify(stored); +truthStore.set("strategy_truth_snapshot", bytes); Date.now = () => truthNow; await runTruthRoute( +"R_STORAGE.ttl.binding_readback_just_after", truthGetRequest(), truthEnv, "fresh snapshot with binding readback ttl+1ms old", +"response data_status=stale; KV byte-identical ready", async (response) => { const body = await response.json(); +assert.equal(body.data_status, "stale"); assert.equal(truthStore.get("strategy_truth_snapshot"), bytes); }, ); Date.now = realDateNow; } + +const securityCanaryFields = [ +"binding_readback_source", "decision_label", "decision_reason", "errors", "health_as_of", "health_source_revision", +"review_evidence_package_id", "review_requested_stage", "scalar_kelly_readiness", "scalar_risk", "scalar_validation", ]; for (const field of securityCanaryFields) { +for (const [kind, canary] of [ +["credential_shape", `ghp_${"x".repeat(36)}`], +["private_path", "/Users/synthetic/private/security-canary"], ]) { const raw = structuredClone(routeTruth); +if (field === "binding_readback_source") raw.profiles[0].bindings[0].readback_source = canary; +if (field === "decision_label") raw.profiles[0].health.decision.label = canary; if (field === "decision_reason") raw.profiles[0].health.decision.reason = canary; +if (field === "errors") raw.errors = [canary]; if (field === "health_as_of") raw.profiles[0].health.as_of = canary; +if (field === "health_source_revision") raw.profiles[0].health.source_revision = canary; +if (field === "review_evidence_package_id") raw.profiles[0].health.review.evidence_package_id = canary; +if (field === "review_requested_stage") raw.profiles[0].health.review.requested_stage = canary; +if (field.startsWith("scalar_")) raw.profiles[0].health.review[field.slice(7)] = { metric: canary }; const priorKv = truthStore.get("strategy_truth_snapshot"); +const priorAudit = truthStore.get("audit_log"); await runTruthRoute( +`S_SECURITY_COMPAT.canary.${field}.${kind}`, truthPostRequest(raw), truthEnv, `${field}=${kind} synthetic canary via POST/KV/GET/audit/error`, +"exact canary absent from POST response, KV bytes, GET body, audit_log and error surface", async (response) => { const postBytes = await response.text(); +const kvBytes = truthStore.get("strategy_truth_snapshot") || ""; const auditBytes = truthStore.get("audit_log") || ""; +const getResponse = await worker.fetch(truthGetRequest(), truthEnv); const getBytes = await getResponse.text(); assert.equal(getResponse.status, 200); +for (const bytes of [postBytes, kvBytes, getBytes, auditBytes]) assert.equal(bytes.includes(canary), false); +if (field === "binding_readback_source") { assert.equal(response.status, 400); assert.equal(kvBytes, priorKv); assert.equal(auditBytes, priorAudit); } +else assert.equal(response.status, 200); }, ); } } const detachPaths = [ +"binding", "components", "decision", "errors", "freshness", "health", "input_provenance", "profile", "review", "scalar_map", "summary", ]; for (const pathName of detachPaths) { +runTruthProof( +`S_SECURITY_COMPAT.detach.${pathName}`, "__test.normalizeStrategyTruthSnapshot detached canonical output", `mutate caller/output nested ${pathName} after normalization`, +"caller unchanged and output shares no mutable nested object", () => { const raw = makeTruthBaseline(); const original = structuredClone(raw); +const output = __test.normalizeStrategyTruthSnapshot(raw, "detach proof", truthNow); assert.deepEqual(raw, original); assert.notEqual(output, raw); +assert.notEqual(output.input_provenance, raw.input_provenance); assert.notEqual(output.summary, raw.summary); assert.notEqual(output.profiles[0], raw.profiles[0]); +assert.notEqual(output.profiles[0].bindings[0], raw.profiles[0].bindings[0]); assert.notEqual(output.profiles[0].health, raw.profiles[0].health); +assert.notEqual(output.profiles[0].health.components, raw.profiles[0].health.components); assert.notEqual(output.profiles[0].health.decision, raw.profiles[0].health.decision); +assert.notEqual(output.profiles[0].health.review, raw.profiles[0].health.review); assert.notEqual(output.profiles[0].health.freshness, raw.profiles[0].health.freshness); +assert.notEqual(output.errors, raw.errors); if (pathName === "binding") output.profiles[0].bindings[0].binding_id = "mutated"; +if (pathName === "components") output.profiles[0].health.components.performance = 1; if (pathName === "decision") output.profiles[0].health.decision.code = "mutated"; +if (pathName === "errors") output.errors.push("mutated_output"); if (pathName === "freshness") output.profiles[0].health.freshness.status = "stale"; +if (pathName === "health") output.profiles[0].health.as_of = "mutated"; if (pathName === "input_provenance") output.input_provenance.freshness = "stale"; +if (pathName === "profile") output.profiles[0].strategy_profile = "mutated"; if (pathName === "review") output.profiles[0].health.review.requested_stage = "mutated"; +if (pathName === "scalar_map") output.profiles[0].health.review.validation.Pass = false; if (pathName === "summary") output.summary.live = 0; +assert.deepEqual(raw, original); }, ); } +for (const forbidden of ["account", "capital", "leverage", "order", "position"]) { runTruthProof( +`S_SECURITY_COMPAT.forbidden_field_scan.${forbidden}`, "__test.normalizeStrategyTruthSnapshot closed and sanitizing paths", +`${forbidden} canary injected at top/profile/binding/health/error positions`, "strict positions reject; sanitizing positions omit field and canary", () => { +const canary = `synthetic-${forbidden}-canary`; for (const target of ["top", "profile", "binding"]) { const raw = makeTruthBaseline(); if (target === "top") raw[forbidden] = canary; +if (target === "profile") raw.profiles[0][forbidden] = canary; if (target === "binding") raw.profiles[0].bindings[0][forbidden] = canary; +assert.throws(() => __test.normalizeStrategyTruthSnapshot(raw, "forbidden strict", truthNow)); } const raw = makeTruthBaseline(); raw.profiles[0].health[forbidden] = canary; +raw.errors.push(canary); const canonical = __test.normalizeStrategyTruthSnapshot(raw, "forbidden sanitize", truthNow); assert.equal(JSON.stringify(canonical).includes(canary), false); +assert.equal(JSON.stringify(canonical).includes(`\"${forbidden}\"`), false); }, ); } await runTruthRoute( +"S_SECURITY_COMPAT.legacy.health_auth_error_fixture", new Request("https://switch.example/api/internal/sync-strategy-health", { +method: "POST", headers: { Authorization: "Bearer wrong-value", "Content-Type": "application/json" }, body: "{}", }), healthEnv, "wrong dedicated legacy health token", +"HTTP 401 redacted legacy error", async (response) => assert.equal(response.status, 401), ); await runTruthRoute( +"S_SECURITY_COMPAT.legacy.health_get_fixture", new Request("https://switch.example/api/strategy-health", { headers: healthCookieHeaders }), healthEnv, +"authenticated unchanged legacy health GET fixture", "HTTP 200 legacy strategy_health_dashboard.v1", +async (response) => assert.equal((await response.json()).schema_version, "strategy_health_dashboard.v1"), ); await runTruthRoute( +"S_SECURITY_COMPAT.legacy.health_sync_fixture", new Request("https://switch.example/api/internal/sync-strategy-health", { method: "POST", +headers: { Authorization: `Bearer ${healthSyncValue}`, "Content-Type": "application/json" }, +body: JSON.stringify({ ...healthPayload, data_status: "ready", generated_at: new Date().toISOString(), computed_at: new Date().toISOString() }), }), +healthEnv, "unchanged accepted legacy sync fixture", +"HTTP 200 legacy strategy_count metadata", async (response) => assert.equal(response.status, 200), ); const legacyTtlStored = JSON.parse(healthStore.get("strategy_health_snapshot")); +legacyTtlStored.computed_at = new Date(Date.now() - 301000).toISOString(); healthStore.set("strategy_health_snapshot", JSON.stringify(legacyTtlStored)); await runTruthRoute( +"S_SECURITY_COMPAT.legacy.health_ttl_fixture", new Request("https://switch.example/api/strategy-health", { headers: healthCookieHeaders }), +{ ...healthEnv, STRATEGY_HEALTH_STALE_TTL_SECONDS: "300" }, "legacy health GET with 300-second TTL", "legacy ready snapshot transitions response-only stale", +async (response) => assert.equal((await response.json()).data_status, "stale"), ); runTruthProof( +"S_SECURITY_COMPAT.legacy.helpers_source_unchanged", "legacy health helper source bytes", "hash exact helper slice from normalize components through errors", +"SHA-256=faf52d4c428d0ea42bd3b378d7e3addac335f3016ae8068d17452dfe7dc0672e", () => { const source = readFileSync(resolve(root, "web/strategy-switch-console/worker.js"), "utf8"); +const helperSlice = source.slice(source.indexOf("function normalizeStrategyHealthComponents"), source.indexOf("function emptyStrategyHealthPayload")); +assert.equal(createHash("sha256").update(helperSlice).digest("hex"), "faf52d4c428d0ea42bd3b378d7e3addac335f3016ae8068d17452dfe7dc0672e"); }, ); runTruthProof( +"S_SECURITY_COMPAT.legacy.schema_digest", "schemas/strategy-health-dashboard.v1.schema.json", "hash exact-base legacy health Schema bytes", +"SHA-256=3152782db387fb2a1f115355f6ee74bfd01ca577234f78673e9be73771a24765", () => assert.equal( +createHash("sha256").update(readFileSync(resolve(root, "schemas/strategy-health-dashboard.v1.schema.json"))).digest("hex"), +"3152782db387fb2a1f115355f6ee74bfd01ca577234f78673e9be73771a24765", ), ); truthStore.set("strategy_truth_snapshot", JSON.stringify(rejectedRouteTruth)); await runTruthRoute( +"S_SECURITY_COMPAT.no_raw_echo.corrupt_get_private_path", truthGetRequest(), truthEnv, "corrupted stored binding private-path canary", "unavailable body omits exact canary", +async (response) => { assert.equal(response.status, 200); const body = await response.json(); assert.equal(body.data_status, "unavailable"); +assert.equal(JSON.stringify(body).includes("/Users/synthetic/private"), false); }, ); await runTruthRoute( +"S_SECURITY_COMPAT.no_raw_echo.rejected_post_private_path", truthPostRequest(rejectedRouteTruth), truthEnv, "rejected POST strict private-path canary", +"HTTP 400 error body omits exact canary", async (response) => { assert.equal(response.status, 400); assert.equal((await response.text()).includes(rejectedRouteCanary), false); }, ); +const schemaRun = truthSchema ? spawnSync("python3", ["-c", [ "import json,sys", "from jsonschema import Draft202012Validator", "payload=json.load(sys.stdin)", +"validator=Draft202012Validator(payload['schema'])", "[validator.validate(case['value']) for case in payload['cases']]", ].join("; ")], { +input: JSON.stringify({ schema: truthSchema, cases: truthAccepted }), encoding: "utf8", }) : { status: 1, stderr: "missing truth Schema entrypoint" }; if (schemaRun.status === 0) { +const schemaPassedIds = new Set(truthAccepted.map((item) => item.case_id)); for (const receipt of truthReceipts) { +if (receipt.schema_target === "schemas/strategy-truth-dashboard.v1.schema.json" && schemaPassedIds.has(receipt.case_id)) { receipt.schema_result = "PASS"; } } } runTruthProof( +"W_SCALAR.schema_each_accepted", "Draft202012Validator(strategy-truth-dashboard.v1.schema.json)", "all accepted W_SCALAR canonical outputs", "every accepted scalar output Schema PASS", +() => { +const scalarAccepted = truthReceipts.filter((item) => item.case_id.startsWith("W_SCALAR.") && item.disposition === "accept"); assert.ok(scalarAccepted.length > 0); +assert.ok(scalarAccepted.every((item) => item.schema_result === "PASS")); }, "schemas/strategy-truth-dashboard.v1.schema.json", ); runTruthProof( +"C_FIXED_POINT.each_worker_accepted_output", "normalizeStrategyTruthSnapshot -> truth Schema -> normalizeStrategyTruthSnapshot", "every accepted Worker raw-vector canonical output", +"Schema PASS and immediate second normalization deep-equal", () => { assert.equal(schemaRun.status, 0, schemaRun.stderr); for (const item of truthAccepted) { +const bindingTimes = item.value.profiles.flatMap((profile) => profile.bindings.map((binding) => Date.parse(binding.readback_at))); +const fixedNow = Math.max(truthNow, Date.parse(item.value.generated_at || 0), +Date.parse(item.value.computed_at || 0), ...bindingTimes); +const second = __test.normalizeStrategyTruthSnapshot(item.value, `fixed point ${item.case_id}`, fixedNow); assert.deepEqual(second, item.value, item.case_id); } }, +"schemas/strategy-truth-dashboard.v1.schema.json", ); runTruthProof( +"C_FIXED_POINT.worker_schema_each_accepted", "Draft202012Validator(strategy-truth-dashboard.v1.schema.json)", "all accepted Worker cases", +"all 277 accepted exact canonical outputs Schema PASS", () => { assert.equal(schemaRun.status, 0, schemaRun.stderr); assert.equal(truthAccepted.length, 277); }, +"schemas/strategy-truth-dashboard.v1.schema.json", ); runTruthProof( +"C_FIXED_POINT.readback_source_schema_envelope", "both canonical Schema readback_source definitions", "parse deployment and truth Schemas", +"exact {type:string,minLength:1,maxLength:120}; no pattern", () => { +const deploymentSchema = JSON.parse(readFileSync(resolve(root, "schemas/strategy-deployment-bindings.v1.schema.json"), "utf8")); +const exactEnvelope = { type: "string", minLength: 1, maxLength: 120 }; assert.deepEqual(truthSchema.$defs.binding.properties.readback_source, exactEnvelope); +assert.deepEqual(deploymentSchema.$defs.binding.properties.readback_source, exactEnvelope); }, +"schemas/strategy-truth-dashboard.v1.schema.json + schemas/strategy-deployment-bindings.v1.schema.json", ); runTruthProof( +"C_FIXED_POINT.schema_valid_noncanonical_excluded", "truth Schema then normalizeStrategyTruthSnapshot", "Schema-valid canonical fixture with private-path readback_source", +"Schema PASS does not authorize fixed point; Worker rejects", () => { const noncanonical = makeTruthBaseline(); +noncanonical.profiles[0].bindings[0].readback_source = "FiLe:///Users/schema-valid/private/path"; const probe = spawnSync("python3", ["-c", [ "import json,sys", +"from jsonschema import Draft202012Validator", "payload=json.load(sys.stdin)", "Draft202012Validator(payload['schema']).validate(payload['value'])", +].join("; ")], { input: JSON.stringify({ schema: truthSchema, value: noncanonical }), encoding: "utf8" }); assert.equal(probe.status, 0, probe.stderr); +assert.throws(() => __test.normalizeStrategyTruthSnapshot(noncanonical, "schema-valid noncanonical", truthNow)); }, "schemas/strategy-truth-dashboard.v1.schema.json", ); +const expectedTruthSet = new Set(truthExpectedIds); const executedTruthIds = truthReceipts.map((item) => item.case_id); const executedTruthSet = new Set(executedTruthIds); +const missingTruthIds = [...expectedTruthSet].filter((caseId) => !executedTruthSet.has(caseId)); +const duplicateTruthIds = [...executedTruthSet].filter((caseId) => executedTruthIds.filter((item) => item === caseId).length > 1); +const unexpectedTruthIds = [...executedTruthSet].filter((caseId) => !expectedTruthSet.has(caseId)); +const failedTruthIds = truthReceipts.filter((item) => item.assertion_result !== "PASS" || item.schema_result === "FAIL"); +const truthDispositionCounts = Object.fromEntries(["accept", "reject", "proof", "scope"].map((disposition) => [ +disposition, truthReceipts.filter((item) => item.disposition === disposition).length, ])); for (const receipt of truthReceipts) process.stdout.write(`${JSON.stringify(receipt)}\n`); +const truthMatrixSummary = { expected_unique: expectedTruthSet.size, executed_unique: executedTruthSet.size, missing: missingTruthIds, duplicate: duplicateTruthIds, +unexpected: unexpectedTruthIds, failed: failedTruthIds.map((item) => item.case_id), dispositions: truthDispositionCounts, }; +process.stdout.write(`${JSON.stringify({ qrs_v4_worker_matrix: truthMatrixSummary })}\n`); assert.deepEqual( { expected_unique: expectedTruthSet.size, executed_unique: executedTruthSet.size, +missing: missingTruthIds, duplicate: duplicateTruthIds, unexpected: unexpectedTruthIds, dispositions: truthDispositionCounts, }, { expected_unique: 535, executed_unique: 535, missing: [], +duplicate: [], unexpected: [], dispositions: { accept: 277, reject: 200, proof: 57, scope: 1 }, }, "QRS V4 Worker exact matrix set/disposition mismatch", ); +assert.equal(failedTruthIds.length, 0, "QRS V4 Worker production gaps remain"); diff --git a/web/strategy-switch-console/worker.js b/web/strategy-switch-console/worker.js index 4489977..8e80add 100644 --- a/web/strategy-switch-console/worker.js +++ b/web/strategy-switch-console/worker.js @@ -39,6 +39,9 @@ const STRATEGY_HEALTH_DEFAULT_STALE_TTL_SECONDS = 2 * 60 * 60; const STRATEGY_HEALTH_STATUSES = ["healthy", "watch", "review", "critical"]; const STRATEGY_HEALTH_DOMAINS = ["us_equity", "hk_equity", "cn_equity", "crypto"]; const STRATEGY_HEALTH_DATA_STATUSES = ["ready", "unavailable", "stale"]; +const STRATEGY_TRUTH_SNAPSHOT_KEY = "strategy_truth_snapshot"; +const STRATEGY_TRUTH_MAX_BODY_BYTES = 256 * 1024; +const STRATEGY_TRUTH_DEFAULT_STALE_TTL_SECONDS = 2 * 60 * 60; const SUPPORTED_PLATFORMS = ["longbridge", "ibkr", "schwab", "firstrade", "qmt", "binance"]; const SUPPORTED_STRATEGY_DOMAINS = ["us_equity", "hk_equity", "cn_equity", "crypto"]; @@ -161,6 +164,12 @@ export default { if (url.pathname === "/api/strategy-health" && request.method === "GET") { return await strategyHealthResponse(request, env); } + if (url.pathname === "/api/internal/sync-strategy-truth" && request.method === "POST") { + return await syncStrategyTruthResponse(request, env); + } + if (url.pathname === "/api/strategy-truth" && request.method === "GET") { + return await strategyTruthResponse(request, env); + } if (url.pathname === "/api/logout" && request.method === "POST") return logout(request); if (url.pathname === "/api/switch" && request.method === "POST") return await dispatchSwitch(request, env); if (url.pathname === "/app.css") return new Response(APP_CSS, { status: 200, headers: { "Content-Type": "text/css; charset=utf-8", "Cache-Control": "public, max-age=3600" } }); @@ -1393,6 +1402,286 @@ function strategyHealthStaleTtlSeconds(env) { return Math.floor(configured); } +async function syncStrategyTruthResponse(request, env) { + requireStrategyTruthSyncToken(request, env); + if (!hasConfigStore(env)) return json({ ok: false, error: "strategy truth KV is not configured" }, 503); + let snapshot; + try { + const raw = await readBoundedJson(request, STRATEGY_TRUTH_MAX_BODY_BYTES); + snapshot = normalizeStrategyTruthSnapshot(raw, "strategy truth snapshot", Date.now()); + } catch (error) { + return json({ ok: false, error: "invalid strategy truth payload" }, error.status || 400); + } + await writeConfigJson(env, STRATEGY_TRUTH_SNAPSHOT_KEY, snapshot); + try { + await appendAuditLog(env, { + ts: new Date().toISOString(), login: "strategy-truth-sync", action: "sync_strategy_truth", + schema_version: snapshot.schema_version, profile_count: snapshot.summary.profile_count, + data_status: snapshot.data_status, + }); + } catch {} + return json({ ok: true, schema_version: snapshot.schema_version, profile_count: snapshot.summary.profile_count }); +} + +async function strategyTruthResponse(request, env) { + const session = await readSession(request, env); + if (!session?.allowed) return json({ ok: false, error: "login required" }, 401); + if (!hasConfigStore(env)) return json(emptyStrategyTruthPayload("snapshot_unavailable")); + let snapshot; + try { + const stored = await readConfigJson(env, STRATEGY_TRUTH_SNAPSHOT_KEY); + if (!stored) return json(emptyStrategyTruthPayload("snapshot_unavailable")); + snapshot = normalizeStrategyTruthSnapshot(stored, STRATEGY_TRUTH_SNAPSHOT_KEY, Date.now()); + } catch { + return json(emptyStrategyTruthPayload("snapshot_invalid")); + } + const copy = structuredClone(snapshot); + const timestamps = [copy.generated_at, copy.computed_at, + ...copy.profiles.flatMap((profile) => profile.bindings.map((binding) => binding.readback_at)), + ].filter(Boolean).map((value) => Date.parse(value)); + const age = timestamps.length ? Math.max(0, Date.now() - Math.min(...timestamps)) : Number.POSITIVE_INFINITY; + if (copy.data_status === "ready" && age > strategyTruthStaleTtlSeconds(env) * 1000) copy.data_status = "stale"; + return json(copy); +} + +function requireStrategyTruthSyncToken(request, env) { + const expected = String(env.STRATEGY_TRUTH_SYNC_TOKEN || ""); + if (!expected) throw new HttpError("strategy truth sync token is not configured", 500); + const supplied = (request.headers.get("Authorization") || "").match(/^Bearer\s+(.+)$/i)?.[1] || ""; + if (supplied !== expected) throw new HttpError("strategy truth sync token is invalid", 401); +} + +function truthObject(value, fieldName) { + if (!value || Array.isArray(value) || typeof value !== "object") throw new Error(`${fieldName} must be an object`); + return value; +} + +function truthClosed(value, keys, fieldName) { + const source = truthObject(value, fieldName); + if (Object.keys(source).some((key) => !keys.includes(key)) || keys.some((key) => !(key in source))) { + throw new Error(`${fieldName} must be a closed object`); + } + return source; +} + +function truthIdentity(value, fieldName) { + if (typeof value !== "string") throw new Error(`${fieldName} is invalid`); + const text = value.trim().toLowerCase(); + if (!/^[a-z0-9._=-]{1,120}$/.test(text)) throw new Error(`${fieldName} is invalid`); + return text; +} + +function truthHex(value, length, fieldName, nullable = false) { + if (nullable && value === null) return null; + if (typeof value !== "string" || !new RegExp(`^[0-9a-f]{${length}}$`).test(value)) { + throw new Error(`${fieldName} is invalid`); + } + return value; +} + +function truthTimestamp(value, fieldName, now, nullable = false, readback = false) { + if (nullable && value === null) return null; + const text = String(value ?? "").trim(); + const match = text.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,9})?(Z|[+-]\d{2}:\d{2})$/); + if (!match || Number(match[4]) > 23 || Number(match[5]) > 59 || Number(match[6]) > 59) { + throw new Error(`${fieldName} is invalid`); + } + if (match[7] !== "Z" && (Number(match[7].slice(1, 3)) > 23 || Number(match[7].slice(4)) > 59)) { + throw new Error(`${fieldName} is invalid`); + } + const parsed = Date.parse(text); + const calendar = new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3]))); + if (Number.isNaN(parsed) || calendar.getUTCFullYear() !== Number(match[1]) || calendar.getUTCMonth() + 1 !== Number(match[2]) + || calendar.getUTCDate() !== Number(match[3]) || parsed > now + 300000 || (readback && parsed < now - 604800000)) { + throw new Error(`${fieldName} is outside the allowed window`); + } + return text; +} + +function truthStrictSource(value, fieldName, nullable = false) { + const text = sanitizeStrategyHealthText(value, fieldName, 120, true); + if (text === null) { + if (nullable) return null; + throw new Error(`${fieldName} is unsafe`); + } + if (/^file:/i.test(text)) throw new Error(`${fieldName} is unsafe`); + let parsed; + try { parsed = new URL(text); } catch { + if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(text)) throw new Error(`${fieldName} is unsafe`); + return text; + } + const credentialQueryKeys = new Set([ + "accesstoken", "apikey", "authorization", "credential", "password", "secret", "sig", "signature", "token", + "xamzcredential", "xamzsecuritytoken", "xamzsignature", + ]); + if (parsed.username !== "" || parsed.password !== "" + || [...parsed.searchParams.keys()].some((key) => credentialQueryKeys.has(key.toLowerCase().replaceAll(/[-_]/g, "")))) { + throw new Error(`${fieldName} is unsafe`); + } + return text; +} + +function truthHealthScore(value, fieldName) { + if (typeof value === "boolean") throw new Error(`${fieldName} is invalid`); + return normalizeStrategyHealthScore(value, fieldName); +} + +function truthHealthComponents(value, fieldName) { + const source = value && typeof value === "object" && !Array.isArray(value) ? value : {}; + return { + performance: truthHealthScore(source.performance, `${fieldName}.performance`), + risk: truthHealthScore(source.risk, `${fieldName}.risk`), + decay: truthHealthScore(source.decay, `${fieldName}.decay`), + stability: truthHealthScore(source.stability, `${fieldName}.stability`), + operations: truthHealthScore(source.operations, `${fieldName}.operations`), + }; +} + +function truthScalarMap(value) { + if (!value || Array.isArray(value) || typeof value !== "object") return {}; + if (Object.keys(value).length > 12) throw new Error("scalar map has too many properties"); + const result = {}; + for (const key of Object.keys(value).sort()) { + if (!/^[A-Za-z0-9_.-]{1,48}$/.test(key) || /(cookie|key|password|path|private|secret|token)/i.test(key)) continue; + const raw = value[key]; + if (typeof raw === "boolean") result[key] = raw; + else if (typeof raw === "number") { + if (!Number.isFinite(raw) || raw < -1000000 || raw > 1000000) throw new Error("scalar number is invalid"); + result[key] = raw; + } else if (typeof raw === "string") { + const safe = sanitizeStrategyHealthText(raw, "scalar value", 120, true); + if (safe !== null) result[key] = safe; + } + } + return result; +} + +function truthBinding(value, fieldName, now, seen) { + const keys = ["binding_id", "platform_id", "strategy_revision", "execution_mode", "enabled", "deployment_scope", + "config_digest", "readback_revision", "readback_at", "readback_source", "operating_state"]; + const raw = truthClosed(value, keys, fieldName); + const bindingId = truthIdentity(raw.binding_id, `${fieldName}.binding_id`); + if (seen.has(bindingId)) throw new Error("duplicate binding ID"); + seen.add(bindingId); + const executionMode = cleanChoice(raw.execution_mode, ["off", "dry_run", "paper", "live"], `${fieldName}.execution_mode`); + if (typeof raw.enabled !== "boolean" || (raw.enabled && executionMode === "off") || (!raw.enabled && executionMode !== "off")) { + throw new Error("binding enabled/execution_mode conflict"); + } + return { + binding_id: bindingId, + platform_id: cleanChoice(raw.platform_id, ["longbridge", "ibkr", "schwab", "firstrade", "qmt", "binance"], `${fieldName}.platform_id`), + strategy_revision: truthHex(raw.strategy_revision, 40, `${fieldName}.strategy_revision`), + execution_mode: executionMode, enabled: raw.enabled, + deployment_scope: cleanChoice(raw.deployment_scope, ["production", "paper", "research", "disabled"], `${fieldName}.deployment_scope`), + config_digest: truthHex(raw.config_digest, 64, `${fieldName}.config_digest`), + readback_revision: truthHex(raw.readback_revision, 40, `${fieldName}.readback_revision`), + readback_at: truthTimestamp(raw.readback_at, `${fieldName}.readback_at`, now, false, true), + readback_source: truthStrictSource(raw.readback_source, `${fieldName}.readback_source`), + operating_state: cleanChoice(raw.operating_state, ["normal", "watch", "reduced", "quarantined", "retired", "unknown"], `${fieldName}.operating_state`), + }; +} + +function truthHealth(value, fieldName, healthState) { + if (healthState === "unavailable") { + if (value !== null) throw new Error(`${fieldName} must be null when unavailable`); + return null; + } + const raw = truthObject(value, fieldName); + const status = cleanChoice(raw.status, STRATEGY_HEALTH_STATUSES, `${fieldName}.status`); + if (status !== healthState) throw new Error(`${fieldName}.status conflicts with health_state`); + const components = truthHealthComponents(raw.components, `${fieldName}.components`); + const decision = normalizeStrategyHealthDecision(raw.decision, `${fieldName}.decision`); + const reviewSource = raw.review && !Array.isArray(raw.review) && typeof raw.review === "object" ? raw.review : {}; + const freshnessSource = raw.freshness && !Array.isArray(raw.freshness) && typeof raw.freshness === "object" ? raw.freshness : {}; + return { + as_of: sanitizeStrategyHealthText(raw.as_of, `${fieldName}.as_of`, 64, true), status, + score: truthHealthScore(raw.score, `${fieldName}.score`), components, decision, + review: { + requested_stage: sanitizeStrategyHealthText(reviewSource.requested_stage, `${fieldName}.review.requested_stage`, 120, true), + evidence_package_id: sanitizeStrategyHealthText(reviewSource.evidence_package_id, `${fieldName}.review.evidence_package_id`, 120, true), + validation: truthScalarMap(reviewSource.validation), risk: truthScalarMap(reviewSource.risk), + kelly_readiness: truthScalarMap(reviewSource.kelly_readiness), + }, + freshness: { + status: cleanChoice(freshnessSource.status || "unknown", ["fresh", "stale", "unknown"], `${fieldName}.freshness.status`), + age_seconds: normalizeStrategyHealthAge(freshnessSource.age_seconds, `${fieldName}.freshness.age_seconds`), + }, + source_revision: truthStrictSource(raw.source_revision, `${fieldName}.source_revision`, true), + }; +} + +function normalizeStrategyTruthSnapshot(payload, fieldName = "strategy truth snapshot", now = Date.now()) { + const topKeys = ["schema_version", "generated_at", "computed_at", "data_status", "input_provenance", "summary", "profiles", "errors"]; + const raw = truthClosed(payload, topKeys, fieldName); + if (raw.schema_version !== "strategy_truth_dashboard.v1") throw new Error(`${fieldName}.schema_version is unsupported`); + const dataStatus = cleanChoice(raw.data_status, ["ready", "stale", "unavailable"], `${fieldName}.data_status`); + const unavailable = dataStatus === "unavailable"; + const provenance = truthClosed(raw.input_provenance, ["sha256", "source_revision", "config_digest", "freshness"], `${fieldName}.input_provenance`); + const normalizedProvenance = { + sha256: truthHex(provenance.sha256, 64, "input_provenance.sha256", unavailable), + source_revision: truthHex(provenance.source_revision, 40, "input_provenance.source_revision", unavailable), + config_digest: truthHex(provenance.config_digest, 64, "input_provenance.config_digest", unavailable), + freshness: cleanChoice(provenance.freshness, ["fresh", "stale", "unavailable"], "input_provenance.freshness"), + }; + if (unavailable !== (normalizedProvenance.freshness === "unavailable") || unavailable !== Object.values(normalizedProvenance).slice(0, 3).every((item) => item === null)) { + throw new Error("data_status/provenance nullability conflict"); + } + const generatedAt = truthTimestamp(raw.generated_at, `${fieldName}.generated_at`, now, unavailable); + const computedAt = truthTimestamp(raw.computed_at, `${fieldName}.computed_at`, now, unavailable); + if (unavailable !== (generatedAt === null && computedAt === null)) throw new Error("data_status/timestamp nullability conflict"); + if (!Array.isArray(raw.profiles) || raw.profiles.length > 100) throw new Error(`${fieldName}.profiles is invalid`); + const seenProfiles = new Set(); + const profiles = raw.profiles.map((value, index) => { + const keys = ["strategy_profile", "domain", "catalog_stage", "deployment_label", "bindings", "health_state", "health"]; + const profile = truthClosed(value, keys, `${fieldName}.profiles[${index}]`); + const profileId = truthIdentity(profile.strategy_profile, "strategy_profile"); + if (seenProfiles.has(profileId)) throw new Error("duplicate strategy profile ID"); + seenProfiles.add(profileId); + if (!Array.isArray(profile.bindings) || profile.bindings.length > 100) throw new Error("bindings is invalid"); + const bindingIds = new Set(); + const healthState = cleanChoice(profile.health_state, [...STRATEGY_HEALTH_STATUSES, "unavailable"], "health_state"); + return { + strategy_profile: profileId, + domain: cleanChoice(profile.domain, STRATEGY_HEALTH_DOMAINS, "domain"), + catalog_stage: cleanChoice(profile.catalog_stage, ["research_backtest_only", "shadow_candidate", "live_candidate", "runtime_enabled"], "catalog_stage"), + deployment_label: cleanChoice(profile.deployment_label, ["live", "paper", "off", "research_only", "deployment_unknown"], "deployment_label"), + bindings: profile.bindings.map((binding, bindingIndex) => truthBinding(binding, `bindings[${bindingIndex}]`, now, bindingIds)), + health_state: healthState, health: truthHealth(profile.health, "health", healthState), + }; + }); + const summary = truthClosed(raw.summary, ["profile_count", "live", "paper", "off", "research_only", "deployment_unknown"], `${fieldName}.summary`); + const expectedSummary = { profile_count: profiles.length, live: 0, paper: 0, off: 0, research_only: 0, deployment_unknown: 0 }; + for (const profile of profiles) expectedSummary[profile.deployment_label] += 1; + if (Object.keys(expectedSummary).some((key) => summary[key] !== expectedSummary[key])) throw new Error("summary counts do not match profiles"); + const rawErrors = Array.isArray(raw.errors) ? raw.errors : []; + return { + schema_version: "strategy_truth_dashboard.v1", generated_at: generatedAt, computed_at: computedAt, + data_status: dataStatus, input_provenance: normalizedProvenance, summary: expectedSummary, profiles, + errors: uniqueStrings(rawErrors.slice(0, 20).filter((item) => { + const text = String(item || ""); + return /^[a-z][a-z0-9_.-]{0,63}$/.test(text) + && sanitizeStrategyHealthText(text, "truth error", 64, true) !== null + && !/(account|capital|leverage|order|position)/i.test(text); + })), + }; +} + +function emptyStrategyTruthPayload(errorCode) { + return { + schema_version: "strategy_truth_dashboard.v1", generated_at: null, computed_at: null, + data_status: "unavailable", + input_provenance: { sha256: null, source_revision: null, config_digest: null, freshness: "unavailable" }, + summary: { profile_count: 0, live: 0, paper: 0, off: 0, research_only: 0, deployment_unknown: 0 }, + profiles: [], errors: [errorCode], + }; +} + +function strategyTruthStaleTtlSeconds(env) { + const configured = Number(env.STRATEGY_TRUTH_STALE_TTL_SECONDS); + if (!Number.isFinite(configured) || configured < 0 || configured > 604800) return STRATEGY_TRUTH_DEFAULT_STALE_TTL_SECONDS; + return configured; +} + async function syncStrategyProfilesConfig(env, session) { const profiles = normalizeStrategyProfilesPayload(DEFAULT_STRATEGY_PROFILES, "DEFAULT_STRATEGY_PROFILES"); if (!hasConfigStore(env)) return { synced: false, reason: "kv_not_bound", count: profiles.length }; @@ -3068,6 +3357,7 @@ export const __test = { syncDefaultStrategyProfiles: syncStrategyProfilesConfig, syncDefaultStrategyForAccount, normalizeStrategyHealthSnapshot, + normalizeStrategyTruthSnapshot, emptyStrategyHealthPayload, makeSession, supportedDomainsForAccount,