Skip to content

feat: enforce TQQQ calendar endpoint trust - #194

Closed
Pigbibi wants to merge 2 commits into
mainfrom
codex/tqqq-calendar-endpoint-trust-e1-20260725
Closed

feat: enforce TQQQ calendar endpoint trust#194
Pigbibi wants to merge 2 commits into
mainfrom
codex/tqqq-calendar-endpoint-trust-e1-20260725

Conversation

@Pigbibi

@Pigbibi Pigbibi commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add fixture-only digest-first calendar endpoint trust validation
  • enforce exact QQQ/TQQQ session coverage, immutable output, and strict readback
  • add fail-closed regression coverage for the E1 trust matrix

Verification

  • focused tests PASS
  • full suite BASELINE_EQUIVALENT_NOT_REGRESSION
  • python3 -m ruff check src/us_equity_snapshot_pipelines/tqqq_r1_snapshot.py tests/test_tqqq_r1_snapshot.py
  • PYTHONPATH=src python3 -m compileall -q src/us_equity_snapshot_pipelines/tqqq_r1_snapshot.py
  • git diff --check

Co-Authored-By: Codex <noreply@openai.com>
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

🤖 Codex PR Review

🚫 Merge blocked: 2 serious issue(s) found in high-risk files

🚫 Blocking Issues

These issues must be fixed before this PR can be merged:

1. 🔴 [CRITICAL] Security in src/us_equity_snapshot_pipelines/tqqq_r1_snapshot.py

verify_tqqq_calendar_endpoint_trusted_snapshot() reads prices.csv, sha256sums.json, and trust.json with read_bytes() before it checks whether those entries are symlinks. A caller can point output_dir at a directory where one of those names is a symlink to /dev/zero or another unbounded file; the verifier will follow it and can hang or exhaust memory before it ever raises STRICT_READBACK_FAILED. (line 437)

Suggestion: Reject non-regular files before any read, using lstat/is_symlink() (or os.open(..., O_NOFOLLOW)) on each member and only then loading bytes.

2. 🟠 [HIGH] Logic in src/us_equity_snapshot_pipelines/tqqq_r1_snapshot.py

The freshness check only requires next_session to be greater than the last completed session, not that it is the immediate next trading session. A self-consistent endpoint packet can move both next_session and next_session_close_utc forward (for example from 2026-07-27 to 2026-07-28) and still pass on 2026-07-27, so this function will accept a stale calendar and produce a snapshot missing the newly completed session. (line 547)

Suggestion: Validate that next_session/next_session_close_utc represent the exact immediate successor to required_last_completed_session, not just any later session.

ℹ️ Other Findings

1. 🟡 [MEDIUM] Reliability in src/us_equity_snapshot_pipelines/tqqq_r1_snapshot.py

The immutable-create guarantee is subject to a TOCTOU race: the code checks destination.exists() up front, writes into a temp directory, and then calls os.replace(temporary, destination). If another process creates an empty directory at output_dir after the existence check but before os.replace, this code will replace it on POSIX instead of failing closed, overwriting another producer's output despite advertising IMMUTABLE_CREATE_FAILED semantics. (line 566)

Suggestion: Reserve the destination atomically instead of pre-checking it, or use a create/rename flow that fails if output_dir appears at any point after validation.


Review by Codex PR Review bot • PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 148e1fce74

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +433 to +434
if sums != {"prices.csv": member_hashes["prices.csv"], "trust.json": member_hashes["trust.json"]}:
_invalid("STRICT_READBACK_FAILED")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require an external digest for persisted snapshots

When a persisted snapshot is modified together with its metadata, this check provides no tamper protection because both sha256sums.json and trust.json are stored in the same untrusted directory. For example, changing an adjusted-close value, updating trust.json's prices_sha256, and regenerating sha256sums.json passes verification with the original three authority digests, since none of those external digests commits to the snapshot contents. Require the caller to supply a trusted digest of trust.json (as the existing verifier does for its manifest) or otherwise authenticate the output.

Useful? React with 👍 / 👎.

Comment on lines +385 to +387
normalized[PRICE_FIELD] = pd.to_numeric(normalized[PRICE_FIELD], errors="coerce")
if normalized[PRICE_FIELD].isna().any() or not normalized[PRICE_FIELD].map(math.isfinite).all():
_invalid("EXACT_SESSION_SET_MISMATCH")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject non-positive adjusted prices in the trusted path

With otherwise valid calendar and session inputs, zero and negative adjusted-close values pass this validation because they are finite; native boolean values also pass because pd.to_numeric retains them and math.isfinite(True) is true. The materializer then persists and successfully verifies these invalid market prices, which can corrupt downstream return calculations. Apply the same boolean/type and strictly-positive checks used by _normalized_prices before writing the trusted snapshot.

Useful? React with 👍 / 👎.

expected_endpoint_packet_sha256=expected_endpoint_packet_sha256,
expected_runtime_source_identity_sha256=expected_runtime_source_identity_sha256,
)
os.replace(temporary, destination)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make destination installation no-clobber atomic

If another process creates the destination as an empty directory after the earlier existence check but before this call, POSIX os.replace removes that directory and installs the snapshot in its place. This violates the advertised immutable-create behavior and bypasses IMMUTABLE_CREATE_FAILED under a creation race; use an atomic no-replace installation strategy rather than a check followed by replacing rename.

Useful? React with 👍 / 👎.

Comment on lines +529 to +532
endpoint_observed = _parse_utc(endpoint["endpoint_observed_at_utc"], "CALENDAR_SCHEMA_INVALID")
last_close = _parse_utc(endpoint["required_last_completed_close_utc"], "CALENDAR_SCHEMA_INVALID")
next_close = _parse_utc(endpoint["next_session_close_utc"], "CALENDAR_SCHEMA_INVALID")
if endpoint_observed > observation_time or last_close > observation_time or observation_time >= next_close:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate the declared next session before using its close

When a correctly hashed endpoint packet contains inconsistent next_session and next_session_close_utc values, the declared session is never parsed or compared with the close timestamp or last completed session. A packet that declares the next session as 2026-07-27 but supplies a close in 2099 therefore keeps passing the freshness check until 2099, allowing a stale calendar and missing price history to be materialized. Validate that next_session is canonical, follows the last completed session, and corresponds to next_session_close_utc before using that close as the freshness boundary.

Useful? React with 👍 / 👎.

Comment on lines +388 to +391
for symbol, expected in expected_sessions.items():
actual = normalized.loc[normalized["symbol"].eq(symbol), "session"].dt.strftime("%Y-%m-%d").tolist()
if actual != expected:
_invalid("EXACT_SESSION_SET_MISMATCH")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compare session coverage independently of input row order

When callers provide the exact required rows in a different order, this list comparison rejects the input even though the function subsequently sorts the normalized frame before writing it. DataFrame row order is not part of the session set, and ordinary concatenation or sampling can reorder otherwise valid QQQ/TQQQ data, so compare sets or sort each symbol's sessions before checking coverage.

Useful? React with 👍 / 👎.

Comment on lines +423 to +428
try:
names = tuple(sorted(member.name for member in output.iterdir()))
members = {name: (output / name).read_bytes() for name in _TRUSTED_OUTPUT_FILENAMES}
except OSError as exc:
raise SnapshotValidationError("STRICT_READBACK_FAILED") from exc
if names != _TRUSTED_OUTPUT_FILENAMES or any((output / name).is_symlink() for name in _TRUSTED_OUTPUT_FILENAMES):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject non-regular snapshot members before reading them

When an untrusted or damaged snapshot contains a FIFO or device node under one of the expected filenames, read_bytes() runs before any regular-file check and can block indefinitely or consume an unbounded stream instead of failing closed. The later symlink-only test does not protect against these file types; check that every member is a regular, non-symlink file before opening any of them, as the existing R1 verifier does.

Useful? React with 👍 / 👎.

Comment on lines +349 to +352
for line in lines:
entry = _parse_json_object(line.encode("utf-8"), "calendar")
if set(entry) != {"schema", "session", "open_utc", "close_utc"} or entry["schema"] != _CALENDAR_SCHEMA:
_invalid("CALENDAR_SCHEMA_INVALID")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize malformed calendar JSON to the schema status

When a digest-authorized calendar contains malformed NDJSON, this parser raises SnapshotValidationError("invalid calendar") rather than the trust protocol's CALENDAR_SCHEMA_INVALID status. Callers that classify the documented red statuses therefore cannot recognize this calendar-schema failure even though equivalent structural defects take the expected path; catch the parser error here and re-raise it with CALENDAR_SCHEMA_INVALID.

Useful? React with 👍 / 👎.

Comment on lines +544 to +546
destination.parent.mkdir(parents=True, exist_ok=True)
temporary = Path(tempfile.mkdtemp(prefix=f".{destination.name}.", dir=destination.parent))
try:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Convert output creation errors to the immutable failure status

When the destination parent is unwritable, absent on a read-only filesystem, or out of space, mkdir or mkdtemp raises a raw OSError before the cleanup block rather than SnapshotValidationError("IMMUTABLE_CREATE_FAILED"). This bypasses the fail-closed error metadata and status handling added for the trusted consumer in common deployment failures; normalize destination setup and installation I/O errors to the immutable-create status.

Useful? React with 👍 / 👎.

Co-Authored-By: Codex <noreply@openai.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e2e8de71d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +503 to +504
endpoint = _parse_json_object(endpoint_raw, "endpoint packet")
runtime = _parse_json_object(runtime_raw, "runtime source identity")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize malformed authority JSON to trust statuses

When a digest-authorized endpoint packet or runtime anchor contains malformed JSON, duplicate keys, or a non-object root, these calls propagate invalid endpoint packet or invalid runtime source identity from _parse_json_object rather than the corresponding CALENDAR_SCHEMA_INVALID or RUNTIME_SOURCE_IDENTITY_MISMATCH status used by the subsequent structural checks. Consumers that classify the trust protocol's red statuses therefore cannot recognize these authority failures; catch and remap the parser errors here.

Useful? React with 👍 / 👎.

Comment on lines +445 to +446
sums = _parse_json_object(members["sha256sums.json"], "trusted sha256sums")
trust = _parse_json_object(members["trust.json"], "trusted snapshot")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize malformed metadata to the readback status

When the supplied external output digest matches a snapshot whose sha256sums.json or trust.json is malformed, these calls propagate generic invalid trusted ... errors from _parse_json_object instead of STRICT_READBACK_FAILED. This makes an authenticated but structurally invalid persisted snapshot unclassifiable by consumers handling the verifier's strict-readback status; remap metadata parsing failures at this boundary.

Useful? React with 👍 / 👎.

Comment on lines +364 to +365
if opened >= closed or closed.date().isoformat() != session:
_invalid("CALENDAR_SCHEMA_INVALID")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bind each calendar open to its declared session

When a digest-authorized XNYS calendar row has an open_utc on a different date from its declared session but still before close_utc, this condition accepts it because only the close date is bound to the session. Such an internally inconsistent calendar can therefore drive the exact-session snapshot as trusted input; require the normalized open date to equal session as well.

Useful? React with 👍 / 👎.

@Pigbibi

Pigbibi commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

Closing this PR unmerged under CEO authority ef1f9d57-e1bd-48d7-8f06-34ee58fef692.

Exact evidence at closure: base e26b82dc491f27ee80f130c681101191381f6b60; head 7e2e8de71da5e9d39213fc988c9567e60cd68848; test/gate SUCCESS; review / review FAILURE; MERGEABLE/BLOCKED. Canonical review comment 5077077629 (updated_at=2026-07-25T05:21:00Z, body SHA-256 1e40985646d3874bef6bfe23eb9aaa287092e3c2735833270f14236b5bc9a7f1) is substantive. Complete GraphQL review state has 11 unresolved threads.

E1 remediation budget is exhausted (1/1). This is a close-and-park decision, not a review override; no review threads were replied to or resolved, and no merge or additional remediation is authorized.

@Pigbibi Pigbibi closed this Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant