Skip to content

Commit b13e287

Browse files
authored
Merge pull request #525 from QuantStrategyLab/codex/g9-g5b-contracts-20260902
Harden evidence risk and generation reads
2 parents c6bc931 + 9d36d17 commit b13e287

4 files changed

Lines changed: 2129 additions & 25 deletions

File tree

src/quant_platform_kit/common/feature_snapshot.py

Lines changed: 306 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import hashlib
66
import json
7+
import re
78
import shutil
89
import tempfile
910
from dataclasses import dataclass
@@ -27,6 +28,11 @@
2728
DEFAULT_FEATURE_SNAPSHOT_FALLBACK_CACHE_DIR = (
2829
DEFAULT_ARTIFACT_CACHE_DIR / "last_valid_feature_snapshots"
2930
)
31+
_CURRENT_GENERATION_SCHEMA = "current_generation.v1"
32+
_CURRENT_GENERATION_OBJECT_NAMES = ("snapshot", "manifest", "ranking", "release_summary")
33+
_CURRENT_GENERATION_POINTER_FILENAME = "current_generation.json"
34+
_CURRENT_GENERATION_DIGEST_RE = re.compile(r"[0-9a-f]{64}\Z")
35+
_CURRENT_GENERATION_ID_RE = re.compile(r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}\Z")
3036
_MANIFEST_DIAGNOSTIC_FIELDS = (
3137
"price_as_of",
3238
"universe_as_of",
@@ -172,9 +178,253 @@ def _download_remote_object(uri: str, destination: Path) -> None:
172178
destination.write_bytes(get_object_store().read_bytes(uri))
173179

174180

181+
def _is_current_generation_pointer_reference(reference: str) -> bool:
182+
raw_reference = str(reference or "").strip()
183+
return _is_cloud_uri(raw_reference) and raw_reference.endswith(
184+
f"/{_CURRENT_GENERATION_POINTER_FILENAME}"
185+
)
186+
187+
188+
def _reject_duplicate_json_keys(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
189+
result: dict[str, Any] = {}
190+
for key, value in pairs:
191+
if key in result:
192+
raise ValueError("duplicate pointer field")
193+
result[key] = value
194+
return result
195+
196+
197+
def _reject_nonfinite_json_constant(value: str) -> None:
198+
raise ValueError(f"invalid pointer JSON constant: {value}")
199+
200+
201+
def _is_safe_generation_basename(value: object) -> bool:
202+
if not isinstance(value, str) or not value or "\x00" in value:
203+
return False
204+
return (
205+
"/" not in value
206+
and "\\" not in value
207+
and value not in {".", ".."}
208+
and Path(value).name == value
209+
)
210+
211+
212+
def _validate_current_generation_pointer_uri(pointer_uri: str) -> str:
213+
bucket, object_name = _parse_cloud_uri(pointer_uri)
214+
if (
215+
object_name.split("/")[-1] != _CURRENT_GENERATION_POINTER_FILENAME
216+
or any(segment in {"", ".", ".."} for segment in object_name.split("/"))
217+
or any(character.isspace() or character == "\\" for character in object_name)
218+
):
219+
raise ValueError("unsafe current generation pointer URI")
220+
parent = object_name.rsplit("/", 1)[0] if "/" in object_name else ""
221+
return f"{pointer_uri[:5]}{bucket}/{parent}" if parent else f"{pointer_uri[:5]}{bucket}"
222+
223+
224+
def _read_current_generation_pointer(pointer_bytes: bytes) -> dict[str, object]:
225+
try:
226+
text = pointer_bytes.decode("utf-8")
227+
payload = json.loads(
228+
text,
229+
object_pairs_hook=_reject_duplicate_json_keys,
230+
parse_constant=_reject_nonfinite_json_constant,
231+
)
232+
except (UnicodeDecodeError, json.JSONDecodeError, ValueError, TypeError):
233+
raise ValueError("invalid current generation pointer") from None
234+
235+
if not isinstance(payload, dict):
236+
raise ValueError("invalid current generation pointer")
237+
if set(payload) != {
238+
"schema",
239+
"profile",
240+
"generation_id",
241+
"immutable_prefix",
242+
"snapshot_as_of",
243+
"objects",
244+
}:
245+
raise ValueError("invalid current generation pointer fields")
246+
247+
try:
248+
canonical_bytes = json.dumps(
249+
payload,
250+
ensure_ascii=True,
251+
allow_nan=False,
252+
sort_keys=True,
253+
separators=(",", ":"),
254+
).encode("utf-8") + b"\n"
255+
except (TypeError, ValueError):
256+
raise ValueError("invalid current generation pointer") from None
257+
if pointer_bytes != canonical_bytes:
258+
raise ValueError("non-canonical current generation pointer")
259+
260+
if payload["schema"] != _CURRENT_GENERATION_SCHEMA:
261+
raise ValueError("unsupported current generation pointer schema")
262+
if (
263+
not isinstance(payload["profile"], str)
264+
or not payload["profile"]
265+
or payload["profile"] != payload["profile"].strip()
266+
):
267+
raise ValueError("invalid current generation pointer profile")
268+
generation_id = payload["generation_id"]
269+
if not isinstance(generation_id, str) or _CURRENT_GENERATION_ID_RE.fullmatch(generation_id) is None:
270+
raise ValueError("invalid current generation pointer generation_id")
271+
snapshot_as_of = payload["snapshot_as_of"]
272+
if (
273+
not isinstance(snapshot_as_of, str)
274+
or pd.Timestamp(snapshot_as_of).strftime("%Y-%m-%d") != snapshot_as_of
275+
):
276+
raise ValueError("invalid current generation pointer snapshot_as_of")
277+
278+
objects = payload["objects"]
279+
if not isinstance(objects, dict) or set(objects) != set(_CURRENT_GENERATION_OBJECT_NAMES):
280+
raise ValueError("invalid current generation pointer objects")
281+
basenames: set[str] = set()
282+
for name in _CURRENT_GENERATION_OBJECT_NAMES:
283+
item = objects[name]
284+
if not isinstance(item, dict) or set(item) != {"basename", "sha256"}:
285+
raise ValueError("invalid current generation pointer object fields")
286+
basename = item["basename"]
287+
digest = item["sha256"]
288+
if not _is_safe_generation_basename(basename) or basename in basenames:
289+
raise ValueError("invalid current generation pointer basename")
290+
if not isinstance(digest, str) or _CURRENT_GENERATION_DIGEST_RE.fullmatch(digest) is None:
291+
raise ValueError("invalid current generation pointer sha256")
292+
basenames.add(basename)
293+
294+
return payload
295+
296+
297+
def _load_current_generation_feature_snapshot_guarded(
298+
pointer_uri: str,
299+
*,
300+
run_as_of,
301+
required_columns: Iterable[str] | None,
302+
snapshot_date_columns: Iterable[str],
303+
max_snapshot_month_lag: int,
304+
expected_strategy_profile: str | None,
305+
expected_config_name: str | None,
306+
expected_config_path: str | None,
307+
expected_contract_version: str | None,
308+
) -> FeatureSnapshotGuardResult:
309+
pointer_metadata = {
310+
"feature_snapshot_pointer_uri": pointer_uri,
311+
"feature_snapshot_generation_id": None,
312+
"feature_snapshot_immutable_prefix": None,
313+
"feature_snapshot_object_digests": None,
314+
}
315+
try:
316+
prefix_root = _validate_current_generation_pointer_uri(pointer_uri)
317+
with tempfile.TemporaryDirectory(prefix="feature-snapshot-generation-") as temporary_dir:
318+
pointer_path = Path(temporary_dir) / _CURRENT_GENERATION_POINTER_FILENAME
319+
_download_gcs_object(pointer_uri, pointer_path)
320+
payload = _read_current_generation_pointer(pointer_path.read_bytes())
321+
pointer_profile = str(payload["profile"])
322+
if expected_strategy_profile and _normalize_strategy_profile_label(
323+
pointer_profile
324+
) != _normalize_strategy_profile_label(expected_strategy_profile):
325+
raise ValueError("current generation pointer profile mismatch")
326+
generation_id = payload["generation_id"]
327+
immutable_prefix = payload["immutable_prefix"]
328+
expected_prefix = f"{prefix_root}/generations/{generation_id}"
329+
if immutable_prefix != expected_prefix:
330+
raise ValueError("current generation pointer prefix mismatch")
331+
332+
objects = payload["objects"]
333+
object_digests = {
334+
name: objects[name]["sha256"] for name in _CURRENT_GENERATION_OBJECT_NAMES
335+
}
336+
pointer_metadata.update(
337+
{
338+
"feature_snapshot_generation_id": generation_id,
339+
"feature_snapshot_immutable_prefix": immutable_prefix,
340+
"feature_snapshot_object_digests": dict(object_digests),
341+
}
342+
)
343+
local_paths: dict[str, Path] = {}
344+
for name in _CURRENT_GENERATION_OBJECT_NAMES:
345+
basename = objects[name]["basename"]
346+
object_uri = f"{immutable_prefix}/{basename}"
347+
local_path = Path(temporary_dir) / f"{name}-{basename}"
348+
_download_gcs_object(object_uri, local_path)
349+
if _sha256_file(local_path) != object_digests[name]:
350+
return FeatureSnapshotGuardResult(
351+
frame=None,
352+
metadata=_build_guard_metadata(
353+
snapshot_path=pointer_uri,
354+
decision="fail_closed",
355+
snapshot_exists=False,
356+
**pointer_metadata,
357+
fail_reason="feature_snapshot_pointer_object_digest_mismatch",
358+
),
359+
)
360+
local_paths[name] = local_path
361+
362+
result = _load_feature_snapshot_guarded_without_fallback(
363+
str(local_paths["snapshot"]),
364+
run_as_of=run_as_of,
365+
required_columns=required_columns,
366+
snapshot_date_columns=snapshot_date_columns,
367+
max_snapshot_month_lag=max_snapshot_month_lag,
368+
manifest_path=str(local_paths["manifest"]),
369+
require_manifest=True,
370+
expected_strategy_profile=expected_strategy_profile or pointer_profile,
371+
expected_config_name=expected_config_name,
372+
expected_config_path=expected_config_path,
373+
expected_contract_version=expected_contract_version,
374+
)
375+
metadata = dict(result.metadata)
376+
metadata.update(pointer_metadata)
377+
metadata.update(
378+
{
379+
"feature_snapshot_path": pointer_uri,
380+
"snapshot_path": pointer_uri,
381+
"snapshot_source_uri": f"{immutable_prefix}/{objects['snapshot']['basename']}",
382+
"snapshot_manifest_path": f"{immutable_prefix}/{objects['manifest']['basename']}",
383+
"snapshot_manifest_source_uri": f"{immutable_prefix}/{objects['manifest']['basename']}",
384+
"snapshot_local_path": None,
385+
"snapshot_manifest_local_path": None,
386+
}
387+
)
388+
if result.metadata.get("snapshot_guard_decision") != "proceed":
389+
metadata = _build_guard_metadata(
390+
snapshot_path=pointer_uri,
391+
decision="fail_closed",
392+
snapshot_exists=False,
393+
**pointer_metadata,
394+
fail_reason="feature_snapshot_pointer_guard_failed",
395+
)
396+
return FeatureSnapshotGuardResult(frame=None, metadata=metadata)
397+
if result.metadata.get("snapshot_guard_decision") == "proceed" and str(
398+
result.metadata.get("snapshot_as_of")
399+
)[:10] != payload["snapshot_as_of"]:
400+
return FeatureSnapshotGuardResult(
401+
frame=None,
402+
metadata={
403+
**metadata,
404+
"snapshot_guard_decision": "fail_closed",
405+
"fail_reason": "feature_snapshot_pointer_snapshot_as_of_mismatch",
406+
},
407+
)
408+
return FeatureSnapshotGuardResult(frame=result.frame, metadata=metadata)
409+
except Exception:
410+
return FeatureSnapshotGuardResult(
411+
frame=None,
412+
metadata=_build_guard_metadata(
413+
snapshot_path=pointer_uri,
414+
decision="fail_closed",
415+
snapshot_exists=False,
416+
**pointer_metadata,
417+
fail_reason="feature_snapshot_pointer_read_failed",
418+
),
419+
)
420+
421+
175422
# Backward-compatible aliases
176423
_parse_gcs_uri = _parse_cloud_uri
177-
_download_gcs_object = _download_remote_object
424+
425+
426+
def _download_gcs_object(uri: str, destination: Path) -> None:
427+
_download_remote_object(uri, destination)
178428

179429

180430
def _cache_path_for_remote_artifact(reference: str) -> Path:
@@ -264,6 +514,34 @@ def load_feature_snapshot_guarded(
264514
) -> FeatureSnapshotGuardResult:
265515
"""Load a guarded snapshot, optionally falling back to the last valid artifact."""
266516

517+
raw_path = str(path or "").strip()
518+
if _is_current_generation_pointer_reference(raw_path):
519+
if str(manifest_path or "").strip() not in {"", raw_path}:
520+
return FeatureSnapshotGuardResult(
521+
frame=None,
522+
metadata=_build_guard_metadata(
523+
snapshot_path=raw_path,
524+
decision="fail_closed",
525+
snapshot_exists=False,
526+
feature_snapshot_pointer_uri=raw_path,
527+
feature_snapshot_generation_id=None,
528+
feature_snapshot_immutable_prefix=None,
529+
feature_snapshot_object_digests=None,
530+
fail_reason="feature_snapshot_pointer_manifest_mismatch",
531+
),
532+
)
533+
return _load_current_generation_feature_snapshot_guarded(
534+
raw_path,
535+
run_as_of=run_as_of,
536+
required_columns=required_columns,
537+
snapshot_date_columns=snapshot_date_columns,
538+
max_snapshot_month_lag=max_snapshot_month_lag,
539+
expected_strategy_profile=expected_strategy_profile,
540+
expected_config_name=expected_config_name,
541+
expected_config_path=expected_config_path,
542+
expected_contract_version=expected_contract_version,
543+
)
544+
267545
fallback_context = _feature_snapshot_fallback_context(
268546
path=path,
269547
manifest_path=manifest_path,
@@ -339,6 +617,33 @@ def _load_feature_snapshot_guarded_without_fallback(
339617
),
340618
)
341619

620+
if _is_current_generation_pointer_reference(raw_path):
621+
if str(manifest_path or "").strip() not in {"", raw_path}:
622+
return FeatureSnapshotGuardResult(
623+
frame=None,
624+
metadata=_build_guard_metadata(
625+
snapshot_path=raw_path,
626+
decision="fail_closed",
627+
snapshot_exists=False,
628+
feature_snapshot_pointer_uri=raw_path,
629+
feature_snapshot_generation_id=None,
630+
feature_snapshot_immutable_prefix=None,
631+
feature_snapshot_object_digests=None,
632+
fail_reason="feature_snapshot_pointer_manifest_mismatch",
633+
),
634+
)
635+
return _load_current_generation_feature_snapshot_guarded(
636+
raw_path,
637+
run_as_of=run_as_of,
638+
required_columns=required_columns,
639+
snapshot_date_columns=snapshot_date_columns,
640+
max_snapshot_month_lag=max_snapshot_month_lag,
641+
expected_strategy_profile=expected_strategy_profile,
642+
expected_config_name=expected_config_name,
643+
expected_config_path=expected_config_path,
644+
expected_contract_version=expected_contract_version,
645+
)
646+
342647
manifest_reference = _resolve_manifest_reference(raw_path, manifest_path)
343648
if _is_cloud_uri(raw_path) or _is_cloud_uri(manifest_reference):
344649
try:

0 commit comments

Comments
 (0)