Skip to content

fix(destination): require fresh resolution on redirects - #92

Draft
seonghobae wants to merge 5 commits into
feat/resolution-freshness-authority-mainfrom
fix/redirect-resolution-freshness
Draft

fix(destination): require fresh resolution on redirects#92
seonghobae wants to merge 5 commits into
feat/resolution-freshness-authority-mainfrom
fix/redirect-resolution-freshness

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Buyer/security gap

Stacked follow-up to #47. The prerequisite introduces bounded FreshResolutionSnapshot authority, but its existing RedirectGuard::authorize_redirect still accepted the untimed ResolutionSnapshot. 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 is b20bd4eec8ebe6423b69c39d6edc0f0d0e3639e3.

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, and crates/originweave-destination/tests/redirect_policy.rs. Earlier references to prerequisite 79cf275686e2376a51783a2d03128eca21e7c0e5 and child 21da64dc2dcc7e22559fb4619e20224e91e02914 are historical lineage only. No prerequisite or predecessor check/review transfers.

Keep Draft while #47 remains active.

TDD / RCA sequence

  1. Exact test-only head 98bb8ee99ec685f19091d6b6094ac7861872292b added a realistic regression that gives a redirect target a two-second FreshResolutionSnapshot, attempts authorization exactly at the exclusive validity deadline, and requires the hop to fail without mutating redirect-chain state.
  2. CI run 31523936438, Rust contracts job 93887508525, passed repository contracts and canonical formatting, then reached the intended production boundary: cargo check --locked --workspace --all-targets failed because authorize_redirect still accepted &ResolutionSnapshot without trusted current time and RedirectError::ResolutionFreshnessDenied did not exist. This is the valid RED.
  3. Production head 5516055bd70e687d6d76dc8660e90f003d3c0432 added the narrow freshness composition and migrated the existing redirect tests. CI then exposed only a canonical rustfmt hunk.
  4. Formatting-only head b796564d059f7bcbd8177617b6fd46c6edc7dda1 applied exactly that rustfmt delta.
  5. Subsequent non-destructive prerequisite alignments preserved that implementation while advancing to current exact head b20bd4eec8ebe6423b69c39d6edc0f0d0e3639e3.

Implemented boundary

RedirectGuard::authorize_redirect now:

  • requires the prerequisite FreshResolutionSnapshot rather than an untimed resolution snapshot;
  • requires caller-supplied trusted monotonic current_time from the same clock domain as resolution approval;
  • preserves exact readable-origin and resolution-origin binding checks;
  • fails closed before any redirect-chain state mutation when use occurs before approval or at/after the exclusive freshness deadline;
  • preserves existing HTTPS downgrade, redirect-cycle and hop-limit semantics; and
  • wraps the existing typed DestinationError::ResolutionUseBeforeApproval / ResolutionApprovalExpired outcomes as RedirectError::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 b20bd4eec8ebe6423b69c39d6edc0f0d0e3639e3 against exact live prerequisite 8b4b9901f07b27727c84c73f58fb88f011551981:

  • fresh ancestry: ahead 5 / behind 0, merge base equal to current feat(destination): bound resolution freshness authority #47;
  • CI run 31980276705: success;
  • Rust contracts job 95245805236: success, including repository contracts, formatting, locked workspace/all-target check, full tests, strict Clippy, and rustdoc;
  • Production coverage job 95245805259: success, including exact owned-production function/line/region/branch enforcement;
  • GitHub reports the Draft mergeable;
  • formal reviews currently returned: none; and
  • inline review threads currently returned: none.

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 FreshResolutionSnapshot does 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.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2928350e-5bd6-4b01-8560-42b101a01b75

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

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