fix(destination): require fresh resolution on redirects - #92
Draft
seonghobae wants to merge 5 commits into
Draft
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Buyer/security gap
Stacked follow-up to #47. The prerequisite introduces bounded
FreshResolutionSnapshotauthority, but its existingRedirectGuard::authorize_redirectstill accepted the untimedResolutionSnapshot. That left redirect hops as a first-party bypass: a target resolution could be origin-matched yet used after its freshness window expired.Live dependency / stack state
The independently resolved live prerequisite is exact #47 head
8b4b9901f07b27727c84c73f58fb88f011551981. Current exact #92 head isb20bd4eec8ebe6423b69c39d6edc0f0d0e3639e3.Fresh ancestry reports #92 ahead 5 / behind 0, with merge base exactly equal to current #47. The exact current semantic delta is limited to
crates/originweave-destination/src/redirect.rs,crates/originweave-destination/tests/redirect_freshness.rs, andcrates/originweave-destination/tests/redirect_policy.rs. Earlier references to prerequisite79cf275686e2376a51783a2d03128eca21e7c0e5and child21da64dc2dcc7e22559fb4619e20224e91e02914are historical lineage only. No prerequisite or predecessor check/review transfers.Keep Draft while #47 remains active.
TDD / RCA sequence
98bb8ee99ec685f19091d6b6094ac7861872292badded a realistic regression that gives a redirect target a two-secondFreshResolutionSnapshot, attempts authorization exactly at the exclusive validity deadline, and requires the hop to fail without mutating redirect-chain state.31523936438, Rust contracts job93887508525, passed repository contracts and canonical formatting, then reached the intended production boundary:cargo check --locked --workspace --all-targetsfailed becauseauthorize_redirectstill accepted&ResolutionSnapshotwithout trusted current time andRedirectError::ResolutionFreshnessDenieddid not exist. This is the valid RED.5516055bd70e687d6d76dc8660e90f003d3c0432added the narrow freshness composition and migrated the existing redirect tests. CI then exposed only a canonical rustfmt hunk.b796564d059f7bcbd8177617b6fd46c6edc7dda1applied exactly that rustfmt delta.b20bd4eec8ebe6423b69c39d6edc0f0d0e3639e3.Implemented boundary
RedirectGuard::authorize_redirectnow:FreshResolutionSnapshotrather than an untimed resolution snapshot;current_timefrom the same clock domain as resolution approval;DestinationError::ResolutionUseBeforeApproval/ResolutionApprovalExpiredoutcomes asRedirectError::ResolutionFreshnessDenied, preserving the standard error source.Focused regressions prove exact-boundary expiry, pre-approval use rejection, no chain advancement on freshness denial, stable credential-free error text/source, and migration of every existing redirect authorization path through fresh resolution authority.
Current exact-head evidence
On unchanged exact head
b20bd4eec8ebe6423b69c39d6edc0f0d0e3639e3against exact live prerequisite8b4b9901f07b27727c84c73f58fb88f011551981:31980276705: success;95245805236: success, including repository contracts, formatting, locked workspace/all-target check, full tests, strict Clippy, and rustdoc;95245805259: success, including exact owned-production function/line/region/branch enforcement;Security/SAST/central workflows not generated for this stacked Draft base are absent and are not represented as passing. Skipped formatting-diagnostic helper steps are not passing evidence. No predecessor-head, prerequisite-head, synthetic-merge, queued, pending, skipped, cancelled, absent, stale, status-only, or model-only evidence is promoted as current proof.
Truth boundary
This is deterministic per-hop destination authority only. It performs no DNS lookup, socket I/O, HTTP redirect following, wall-clock read, proxy/PAC execution, TLS/browser/model operation, persistence, or runtime clock attestation. Constructing a
FreshResolutionSnapshotdoes not prove the resolver or clock is trusted; the higher-layer resolver/network/browser adapter must supply independently validated resolution evidence and current time from the same trusted monotonic domain.This PR is a partial hardening slice under #28/#47 and does not close either issue. Keep Draft while #47 remains active; any prerequisite or current-head movement requires fresh exact-head/live-base validation. Passing automation is not independent approval, and the scheduled actor does not merge or self-approve.