Skip to content

AC-179 - Send the context id deletion request from the ads client over OHTTP - #7630

Open
copyrighthero wants to merge 3 commits into
mainfrom
jira/ac-179--ohttp-context-id-deletion
Open

copyrighthero wants to merge 3 commits into
mainfrom
jira/ac-179--ohttp-context-id-deletion

Conversation

@copyrighthero

@copyrighthero copyrighthero commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Send the DELETE /v1/delete_user request for a retired context id from the ads client, over the same OHTTP channel as the ad request, instead of as a direct request from the embedded context_id component.

Changes

  • Adds MARSClient::delete_user(context_id, ohttp): DELETE /v1/delete_user with {"context_id": ...} through MARSTransport, 5 s timeout on the relay request, over the ads-client OHTTP channel when asked. If OHTTP is asked for and the channel is not configured it fails with OhttpChannelNotConfigured; there is no fallback to a direct request.
  • Disables the component's own request by passing DISABLE_CONTEXT_ID_COMPONENT_DELETION (true) as running_in_test_automation, the same thing Firefox does for its JS-side component in browser/modules/ContextId.sys.mjs. This replaces the cfg!(test) passed there before, which only disabled it in test builds.
  • Adds ContextIdDeletionQueue as the ContextIdCallback: rotated ids are queued, and request_ads takes them before its ad fetch and sends their deletions right after it, with that call's OHTTP setting. The flush runs whether or not the fetch succeeded. Without OHTTP the deletion is skipped and logged; failures are logged and not retried.
  • Behavior change for consumers without an OHTTP channel: consumers that do not configure a viaduct OHTTP channel named ads-client stop sending the deletion request after this lands. The context id still rotates on the same schedule. Configuring the channel and passing ohttp: true on ad requests makes it resume.
  • Updates the ohttp row of MozAdsRequestOptions in the Kotlin, Swift and JavaScript usage docs to say it also applies to the deletion request.
  • Adds unit tests for the request format, the fail-closed path, the skip-without-OHTTP path and flush-after-failed-fetch, plus an env-gated production contract test (ADS_CLIENT_PROD_DELETE_USER_CONTRACT=1 -- --ignored --nocapture). Ran it by hand: HTTP 200 observed 2026-10-14 through the production relay and gateway. It returns without sending unless the env var is set, so CI's --ignored run does not touch production.
  • CHANGELOG entry under v160.0.

No changes to ffi.rs, the binding APIs, or components/context_id/.

For the reviewer: the flush is synchronous inside request_ads, so once per rotation one ad request can take longer (one relay request with a 5 s timeout, plus a 10 s gateway key fetch if the key cache is cold). If the worker direction in #7597 lands first it seems natural to move it there; happy to rebase either way. Two spots worth a close look: get_context_id() and take_all() are separate critical sections, so an overlapping call can drain an id a different call rotated. Since #7647, requests with relevance scores skip get_context_id(), so they never rotate the id, but they still flush any ids already queued. And scope: this changes which path carries the deletion, not when it is sent; it does not address correlation by request timing. The component's own request path will be removed in a follow-up. Thank you so much for taking a look!!

Pull Request checklist

  • Breaking changes: This PR follows our breaking change policy
    • This PR follows the breaking change policy: no breaking API changes. The network behavior change for consumers without an OHTTP channel is described above.
  • Quality: This PR builds and tests run cleanly
  • Tests: Unit tests above, plus a manually run, env-gated production contract test
  • Changelog: Entry added under v160.0 → Ads-Client
  • Dependencies: No new dependencies

@copyrighthero
copyrighthero force-pushed the jira/ac-179--ohttp-context-id-deletion branch from b26e84a to e2a747c Compare October 14, 2026 02:12
@copyrighthero copyrighthero changed the title WIP: AC-179 context id rotation via ohttp AC-179 - Send the context id deletion request from the ads client over OHTTP Oct 14, 2026
@copyrighthero
copyrighthero force-pushed the jira/ac-179--ohttp-context-id-deletion branch from e2a747c to f8d3493 Compare October 14, 2026 19:53
…timeout

Adds a DELETE /v1/delete_user request builder to the MARS client so the
ads client can send the context id deletion itself instead of relying on
the context_id component's direct request. The request goes through
MARSTransport with a 5 s timeout on the relay request and, when asked,
the ads-client OHTTP channel; gateway key retrieval keeps viaduct's own
timeout. When OHTTP is asked for and the channel is not configured the
request fails with OhttpChannelNotConfigured rather than being sent
directly. Without OHTTP the helper sends a direct request; the
OHTTP-only gate lives in the ads client's rotation path.

MARSTransport gains fire_with_timeout, and client_for now takes the
ClientSettings to use instead of always using the default.
…r OHTTP

The embedded ContextIDComponent used to send DELETE /v1/delete_user to
MARS directly whenever the context id rotated, outside the OHTTP channel
the ads client uses for ad requests. The ads client now disables the
component's request (running_in_test_automation = true, as Firefox
already does for its JS-side component) and implements ContextIdCallback
itself with a small queue: rotated ids are collected and flushed right
after each ad fetch, with the OHTTP setting of the request_ads call that
drains them. When that call did not use OHTTP the deletion is skipped
and logged. Failures are logged and not retried.

Consumers that do not configure an OHTTP channel for the ads client
therefore no longer send the deletion request after this change. The
context id still rotates on the same schedule. The usage docs now note
that the ohttp request option also applies to this deletion request.

This also replaces the cfg!(test) that was passed as
running_in_test_automation, a compile-time constant answering a runtime
question, which meant release builds always sent the component's
request.
…e_user

The contract test sends the same DELETE /v1/delete_user the ads client
sends after a rotation, over the production relay and gateway, prints
the status, and checks that MARS answers 200. Because it writes to
production and CI runs this crate with --ignored, it returns without
sending unless ADS_CLIENT_PROD_DELETE_USER_CONTRACT is set; it is meant
to be run by hand with --nocapture and the observed status pasted into
the PR.
@copyrighthero
copyrighthero force-pushed the jira/ac-179--ohttp-context-id-deletion branch from f8d3493 to 3be5fbb Compare October 19, 2026 15:11
@copyrighthero
copyrighthero marked this pull request as ready for review October 19, 2026 17:31
@copyrighthero
copyrighthero requested a review from a team as a code owner October 19, 2026 17:31
@copyrighthero
copyrighthero requested review from thesuzerain and removed request for a team October 19, 2026 17:31

This branch has not been deployed

No deployments
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