Skip to content

Correlate golden migration proof by session - #176

Merged
lawrencecchen merged 5 commits into
mainfrom
fix/golden-migration-session-correlation
Aug 5, 2026
Merged

lawrencecchen merged 5 commits into
mainfrom
fix/golden-migration-session-correlation

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • prove the accepted migration request by its exact session ID in the destination worker journal
  • keep signed before/after connection deltas as telemetry without requiring a racy net increase
  • require journal correlation in both Go and Python evidence validators
  • add a red-before-green regression for concurrent probe drains

Testing

  • go test ./cmd/subrouter-transport-observer -run "^TestGoldenMigrationAllowsConcurrentDestinationConnectionDrain$" -count=1
  • go test ./cmd/subrouter -run "^TestGCPDeploymentEvidenceGateValidatesOutcomes$" -count=1
  • live staging golden reproduced a fresh front session hidden by concurrent aggregate drains, then restored the legacy route without interrupting either original stream

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Correlate the golden migration proof by session and require a post-snapshot liveness proof on the exact destination connection, waiting for that proof before emitting evidence. This makes cutovers reliable under load and verifies the session stayed live in both Go and Python.

  • Bug Fixes
    • Require journal_correlated in destination proof across Go/Python validators.
    • Enforce post_snapshot_liveness in evidence: same connection/session, destination snapshot SHA matches, ordered timestamps, and liveness within 10s.
    • Wait for the liveness request and proof during the handshake; include the liveness proof digest in deploy evidence and fail if missing or late.
    • Relax destination checks: require at least one live public and generation connection; drop the positive before/after delta.
    • Update deploy/gcp/switch-front-migration.sh to issue a liveness challenge, wait for the liveness-proof, and include it; add validate-destination-liveness to deploy/gcp/deployment-contract.py; update the fake client and add regression tests (exact-connection chunk, missing/incorrect liveness, concurrent drains).

Written for commit 941214c. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added destination connection liveness checks during front-end migrations.
    • Migration validation now confirms the destination is reachable on the expected connection and responds within 10 seconds.
    • Deployment evidence now includes connection identity, snapshot linkage, timing, and liveness verification details.
  • Bug Fixes

    • Improved migration handling when destination connections drain concurrently.
    • Prevented transitions when required post-snapshot liveness evidence is missing, stale, or linked to the wrong connection.
    • Added stricter validation for migration response timing and connection matching.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The migration flow now performs a post-snapshot destination liveness handshake. It records connection, session, snapshot, challenge, and timing data, then validates the evidence across Go and Python validators within ten seconds.

Changes

Destination liveness migration flow

Layer / File(s) Summary
Liveness evidence contracts and validators
cmd/subrouter-transport-observer/golden_migration_evidence.go, deploy/gcp/deployment-contract.py, deploy/gcp/validate-deploy-evidence.py
Evidence now includes journal correlation and post-snapshot liveness. Validators check identifiers, snapshot hashes, connection counts, and ordered timestamps.
Observer liveness handshake
cmd/subrouter-transport-observer/golden.go, cmd/subrouter-transport-observer/golden_migration_transition.go
The observer tracks liveness request and proof files, matches response chunks to the exact connection, and validates proofs within the ten-second limit.
Migration switch integration
deploy/gcp/switch-front-migration.sh, cmd/subrouter-transport-observer/testdata/golden_fake_client/main.go
The switch and fake client create destination snapshots, issue liveness challenges, validate proofs, and write liveness metadata to deployment evidence.
Regression and contract coverage
cmd/subrouter-transport-observer/golden_acceptance_regression_test.go, cmd/subrouter/deploy_scripts_test.go
Tests cover propagation boundaries, connection drains, journal correlation, missing evidence, exact connection matching, and timeout rejection.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary change: correlating the golden migration proof with the destination session.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/golden-migration-session-correlation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deploy/gcp/deployment-contract.py`:
- Around line 439-445: The destination proof validation must enforce the same
64-character lowercase hexadecimal format required by destination liveness.
Update command_validate_destination_proof to validate
destination_proof.connection_id with the existing 64-hex rule before
switch-front-migration.sh forwards it, while preserving the current validation
behavior for other proof fields.

In `@deploy/gcp/switch-front-migration.sh`:
- Around line 465-470: Adjust the polling deadline in the liveness-proof loop so
it reserves a margin for stamping liveness_received_at after the proof appears,
rather than using the full DESTINATION_LIVENESS_LIMIT_MS budget. Keep the
existing missing-response failure behavior, and ensure any accepted proof leaves
enough time for received_at - requested_at to remain strictly below the
validators’ 10-second limit.

In `@deploy/gcp/validate-deploy-evidence.py`:
- Around line 1053-1062: Update the canonical destination projection in
validate_migration_snapshot to hash only generation, generation_connections,
inactive_connections, kind, and public_connections, matching
goldenMigrationSnapshotSHA256. Build the canonical object from those fields
before computing
destination_proof.post_snapshot_liveness.destination_snapshot_sha256, while
preserving the existing sorted JSON serialization and SHA-256 comparison.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2694c93a-f6b5-4083-90f8-5334401e77fb

📥 Commits

Reviewing files that changed from the base of the PR and between 3ef7f8d and 5a62893.

📒 Files selected for processing (9)
  • cmd/subrouter-transport-observer/golden.go
  • cmd/subrouter-transport-observer/golden_acceptance_regression_test.go
  • cmd/subrouter-transport-observer/golden_migration_evidence.go
  • cmd/subrouter-transport-observer/golden_migration_transition.go
  • cmd/subrouter-transport-observer/testdata/golden_fake_client/main.go
  • cmd/subrouter/deploy_scripts_test.go
  • deploy/gcp/deployment-contract.py
  • deploy/gcp/switch-front-migration.sh
  • deploy/gcp/validate-deploy-evidence.py

Comment on lines +439 to +445
def command_validate_destination_liveness(args: argparse.Namespace) -> None:
if re.fullmatch(r"[0-9a-f]{64}", args.connection_id) is None:
fail("destination liveness connection_id is invalid")
if re.fullmatch(r"[A-Za-z0-9._:-]{1,256}", args.session_id) is None:
fail("destination liveness session_id is invalid")
if re.fullmatch(r"[0-9a-f]{64}", args.destination_snapshot_sha256) is None:
fail("destination liveness snapshot SHA-256 is 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.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find every producer and consumer of the destination proof connection_id.
set -euo pipefail

rg -n -C3 'connection_id' --glob '*.go' --glob '*.py' --glob '*.sh' \
  | rg -n -C3 'destination|liveness|proof'

Repository: manaflow-ai/subrouter

Length of output: 159


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | sed -n '1,160p'

echo "== connection_id occurrences =="
rg -n -C2 'connection_id' --glob '*.go' --glob '*.py' --glob '*.sh' . || true

echo "== destination/liveness/proof occurrences =="
rg -n -C2 'destination|liveness|proof|switch-front-migration|validate_destination' --glob '*.go' --glob '*.py' --glob '*.sh' . || true

Repository: manaflow-ai/subrouter

Length of output: 50378


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== generate_connection_id definitions/usages =="
rg -n -C3 'generate_connection_id|connection_id|ConnectionID|connectionID' cmd/subrouter cmd/subrouter-transport-observer --glob '*.go'

echo "== production code around ConnectionID =="
sed -n '1,220p' cmd/subrouter-transport-observer/golden_migration_transition.go
echo "== deployment contract relevant sections =="
sed -n '399,470p' deploy/gcp/deployment-contract.py
sed -n '554,580p' deploy/gcp/deployment-conduct.py.bak || true
sed -n '554,580p' deploy/gcp/deployment-contract.py
echo "== switch front relevant sections =="
sed -n '420,478p' deploy/gcp/switch-front-migration.sh
sed -n '508,552p' deploy/gcp/switch-front-migration.sh

echo "== deterministic behavior probe =="
python3 - <<'PY'
import re
ids = ["connection", "64hex" * 8, "64HEX" * 8, "64hex32"]
print("validate_destination_proof_connection_id_valid:", [ids], [bool(id_) for id_ in ids])
print("validate_destination_liveness_connection_id_valid:", [ids], [bool(re.fullmatch(r"[0-9a-f]{64}", id_)) for id_ in ids])
PY

Repository: manaflow-ai/subrouter

Length of output: 50378


Validate the destination proof connection_id with the 64-hex rule before switch-front-migration.sh forwards it.

command_validate_destination_proof accepts any non-empty string for destination_proof.connection_id, but command_validate_destination_liveness only accepts 64 lowercase hex characters. switch-front-migration.sh passes .connection_id from the destination proof into the liveness request, so a non-hex connection identifier can pass the proof validation and then fail the post-switch liveness contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/gcp/deployment-contract.py` around lines 439 - 445, The destination
proof validation must enforce the same 64-character lowercase hexadecimal format
required by destination liveness. Update command_validate_destination_proof to
validate destination_proof.connection_id with the existing 64-hex rule before
switch-front-migration.sh forwards it, while preserving the current validation
behavior for other proof fields.

Comment on lines +465 to +470
while [[ ! -f "${liveness_proof_path}" || -L "${liveness_proof_path}" ]]; do
(( $(epoch_millis) - liveness_requested_ms < DESTINATION_LIVENESS_LIMIT_MS )) \
|| die "golden destination connection produced no response chunk after the destination snapshot"
sleep 0.05
done
liveness_received_at="$(utc_now)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Leave margin between the poll deadline and the evidence deadline.

The loop accepts a proof while elapsed time is under 10000 ms. liveness_received_at is stamped after the loop exits. Both evidence validators reject received_at - requested_at >= 10 s (validate-deploy-evidence.py Lines 999-1000, golden_migration_evidence.go Line 514).

A proof that appears at 9.9 s can therefore produce evidence that both validators reject, and that failure happens after the route switch. Poll against a smaller budget so a late-but-accepted proof cannot produce unvalidatable evidence.

🛡️ Proposed fix to reserve stamping margin
 while [[ ! -f "${liveness_proof_path}" || -L "${liveness_proof_path}" ]]; do
-  (( $(epoch_millis) - liveness_requested_ms < DESTINATION_LIVENESS_LIMIT_MS )) \
+  (( $(epoch_millis) - liveness_requested_ms < DESTINATION_LIVENESS_LIMIT_MS - 500 )) \
     || die "golden destination connection produced no response chunk after the destination snapshot"
   sleep 0.05
 done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
while [[ ! -f "${liveness_proof_path}" || -L "${liveness_proof_path}" ]]; do
(( $(epoch_millis) - liveness_requested_ms < DESTINATION_LIVENESS_LIMIT_MS )) \
|| die "golden destination connection produced no response chunk after the destination snapshot"
sleep 0.05
done
liveness_received_at="$(utc_now)"
while [[ ! -f "${liveness_proof_path}" || -L "${liveness_proof_path}" ]]; do
(( $(epoch_millis) - liveness_requested_ms < DESTINATION_LIVENESS_LIMIT_MS - 500 )) \
|| die "golden destination connection produced no response chunk after the destination snapshot"
sleep 0.05
done
liveness_received_at="$(utc_now)"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/gcp/switch-front-migration.sh` around lines 465 - 470, Adjust the
polling deadline in the liveness-proof loop so it reserves a margin for stamping
liveness_received_at after the proof appears, rather than using the full
DESTINATION_LIVENESS_LIMIT_MS budget. Keep the existing missing-response failure
behavior, and ensure any accepted proof leaves enough time for received_at -
requested_at to remain strictly below the validators’ 10-second limit.

Comment on lines +1053 to +1062
canonical_destination = json.dumps(
destination_after,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
exact(
liveness_snapshot_sha,
hashlib.sha256(canonical_destination).hexdigest(),
"destination_proof.post_snapshot_liveness.destination_snapshot_sha256",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Hash the same five snapshot fields that the Go validator hashes.

goldenMigrationSnapshotSHA256 in cmd/subrouter-transport-observer/golden_migration_evidence.go (Lines 528-541) hashes exactly generation, generation_connections, inactive_connections, kind, and public_connections. This code hashes every key that destination.after contains, because validate_migration_snapshot returns the full parsed object.

Both digests agree for the current producers. If any producer adds one field to destination.after, the Go validator still accepts the document and this validator rejects it with a snapshot-hash failure. Project the same five fields to keep the two validators on one contract.

♻️ Proposed fix to align the canonical projection
-    canonical_destination = json.dumps(
-        destination_after,
-        sort_keys=True,
-        separators=(",", ":"),
-    ).encode("utf-8")
+    canonical_destination = json.dumps(
+        {
+            key: destination_after[key]
+            for key in (
+                "generation",
+                "generation_connections",
+                "inactive_connections",
+                "kind",
+                "public_connections",
+            )
+        },
+        sort_keys=True,
+        separators=(",", ":"),
+    ).encode("utf-8")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
canonical_destination = json.dumps(
destination_after,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
exact(
liveness_snapshot_sha,
hashlib.sha256(canonical_destination).hexdigest(),
"destination_proof.post_snapshot_liveness.destination_snapshot_sha256",
)
canonical_destination = json.dumps(
{
key: destination_after[key]
for key in (
"generation",
"generation_connections",
"inactive_connections",
"kind",
"public_connections",
)
},
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
exact(
liveness_snapshot_sha,
hashlib.sha256(canonical_destination).hexdigest(),
"destination_proof.post_snapshot_liveness.destination_snapshot_sha256",
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/gcp/validate-deploy-evidence.py` around lines 1053 - 1062, Update the
canonical destination projection in validate_migration_snapshot to hash only
generation, generation_connections, inactive_connections, kind, and
public_connections, matching goldenMigrationSnapshotSHA256. Build the canonical
object from those fields before computing
destination_proof.post_snapshot_liveness.destination_snapshot_sha256, while
preserving the existing sorted JSON serialization and SHA-256 comparison.

@lawrencecchen
lawrencecchen merged commit d38e698 into main Aug 5, 2026
7 of 9 checks passed
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