Skip to content

Retain full addresses for broker opt-outs#2872

Draft
noisysocks wants to merge 5 commits into
mainfrom
poc/people-search-now-address-anchor
Draft

Retain full addresses for broker opt-outs#2872
noisysocks wants to merge 5 commits into
mainfrom
poc/people-search-now-address-anchor

Conversation

@noisysocks

@noisysocks noisysocks commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Asana Task/Github Issue: N/A

Description

Preserves the full parse-address output and original address text when scanning broker profiles, then flattens the current street and zipCode so opt-out actions can reference them. The new field mappings use real extracted values when available and fall back to the existing generated values otherwise.

This is a proof of concept for making peoplesearchnow.com the PeopleFinders cluster's opt-out anchor. It includes a sanitised PeopleSearchNow-style HTML fixture which verifies that the current address is selected instead of address history, and that the street, city, state and ZIP survive extraction.

Native persistence and broker-rule schemas live outside this repo and still need verification.

Testing Steps

  • Run npm run test-unit -w injected.
  • Run npm run test-int -w injected -- --project windows --grep "PeopleSearchNow-style" --reporter list.
  • Run npm run tsc && npm run tsc-strict-core.
  • Run npm run build -w injected.

Checklist

Please tick all that apply:

  • I have tested this change locally
  • I have tested this change locally in all supported browsers
  • This change will be visible to users
  • I have added automated tests that cover this change
  • I have ensured the change is gated by config
  • This change was covered by a ship review
  • This change was covered by a tech design
  • Any dependent config has been merged

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Build Branch

Branch pr-releases/poc/people-search-now-address-anchor
Commit 1b83f23e6a
Updated July 16, 2026 at 5:53:41 AM UTC

Static preview entry points

QR codes (mobile preview)
Entry point QR code
Docs QR for docs preview
Static pages QR for static pages preview
Integration pages QR for integration pages preview

Integration commands

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#pr-releases/poc/people-search-now-address-anchor

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", branch: "pr-releases/poc/people-search-now-address-anchor")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/poc/people-search-now-address-anchor
git -C submodules/content-scope-scripts checkout origin/pr-releases/poc/people-search-now-address-anchor
Pin to exact commit

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#1b83f23e6a3e7fd6595a66e97d8553257297a0ee

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", revision: "1b83f23e6a3e7fd6595a66e97d8553257297a0ee")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/poc/people-search-now-address-anchor
git -C submodules/content-scope-scripts checkout 1b83f23e6a3e7fd6595a66e97d8553257297a0ee

@github-actions github-actions Bot added the semver-minor New feature — triggers minor version bump label Jul 16, 2026
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

[Beta] Generated file diff

Time updated: Tue, 21 Jul 2026 02:27:15 GMT

Android
    - android/autofillImport.js
  • android/brokerProtection.js

File has changed

Apple
    - apple/contentScopeIsolated.js

File has changed

Integration
    - integration/contentScope.js

File has changed

Windows
    - windows/contentScope.js

File has changed

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Cursor review was not successful.

This PR requires a manual review and approval from a member of one of the following teams:

  • @duckduckgo/content-scope-scripts-owners
  • @duckduckgo/apple-devs
  • @duckduckgo/android-devs
  • @duckduckgo/team-windows-development
  • @duckduckgo/extension-owners
  • @duckduckgo/config-aor
  • @duckduckgo/breakage-aor
  • @duckduckgo/breakage

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale comment

Web Compatibility & Security Assessment

Risk Level: Low Risk — Broker-protection-only changes (extract/aggregate/fill-form) with no browser API overrides, messaging transport changes, or global prototype/DOM side effects; impact is confined to config-gated data-broker opt-out flows.


Web Compatibility Assessment

File Lines Severity Finding
injected/src/features/broker-protection/extractors/address.js 149–152 warning formatStreetAddress() reassembles components via parse-address normalization (e.g. streetSt). Opt-out forms that validate against the exact page text may reject the filled value even when extraction succeeded. Consider falling back to the unparsed street line from fullAddress when broker configs require verbatim text.
injected/src/features/broker-protection/actions/extract.js 391 warning Address deduplication still keys on `${city},${state}`. Two distinct full addresses in the same city/state will collapse to one entry in addresses[]. More visible now that entries carry streetAddress/fullAddress.
injected/src/features/broker-protection/extractors/address.js 138 info fullAddressStrings() protects only the first `
viavalue.replace('
', marker). Multi-line addresses with multiple line breaks may still split unexpectedly when separator` is set.
injected/src/features/broker-protection/actions/extract.js 384–416 info currentAddress is taken from pre-sort page order (addressFull[0] / addressFullList[0]) while addresses[] is sorted — intentional per unit tests, but broker configs must target the "current" anchor (XPath in PeopleSearchNow test) rather than relying on list position after aggregation.
All runtime files info No API shims, prototype mutations, observers, or viewport/meta changes. Broker protection is remote-config gated and only executes native-orchestrated actions on broker pages — no general third-party site compatibility surface.
Tests only info Integration + unit coverage added (45 specs pass locally). PeopleSearchNow XPath selector correctly scopes to "Current Address:" and excludes "Used to Live:" history.

Security Assessment

File Lines Severity Finding
All runtime files info No changes to captured-globals.js, message bridge, origin validation, or nativeData handling. Extracted address data flows only through existing actionCompleted broker-protection messaging — no new exfiltration vectors.
injected/src/features/broker-protection/actions/fill-form.js 86–89 info New street / zipCode field types write page-scraped PII into broker opt-out form inputs — intentional and scoped to broker automation. Falls back to existing generators when data is absent (data.street || generateStreetAddress()).
injected/src/features/broker-protection/extractors/address.js 116–117 info ...parsed spreads all parse-address output into result objects forwarded to native. Page-controlled DOM text could yield unexpected parser fields, but output stays within the broker-protection trust boundary and is not executed.
injected/src/features/broker-protection/actions/fill-form.js 171–205 info Pre-existing setValueForInput() uses uncaptured Object.getOwnPropertyDescriptor, window.HTMLInputElement, and Event — not introduced by this PR; acceptable in broker-protection context where page scripts are already active.

Recommendations

  1. (warning) Add a unit test where two full addresses share city/state and confirm dedup behaviour is acceptable, or key the Map on fullAddress/streetAddress when present.
  2. (warning) Document in broker config guidance that formatStreetAddress may normalize abbreviations; provide a config escape hatch (e.g. fill fullAddress street line verbatim) if brokers reject normalized values.
  3. (info) Consider replaceAll(' ', marker) (or a global regex) in fullAddressStrings if multi-line addresses become common.
  4. (info) Coordinate privacy-configuration broker action JSON to use the new street/zipCode fill types and PeopleSearchNow-style addressFull XPath anchor before shipping.

Verdict: Approve from a web-compat/security perspective. Changes are well-scoped, tested, and do not touch security-critical infrastructure. Residual risks are broker-specific extraction/fill fidelity, not general web breakage.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

export function formatStreetAddress(address) {
const unit = [address.sec_unit_type, address.sec_unit_num].filter(Boolean).join(' ');
const streetAddress = [address.number, address.prefix, address.street, address.type, address.suffix, unit].filter(Boolean).join(' ');
return streetAddress || null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning (broker fill fidelity): formatStreetAddress() normalizes via parse-address (e.g. streetSt). If an opt-out form validates against the exact scraped span text, the normalized value may be rejected. Consider a verbatim fallback from the street line of fullAddress when available.

const currentAddress = profile.addressFull?.[0] || profile.addressFullList?.[0];
const combinedAddresses = [
...(profile.addressCityState || []),
...(profile.addressCityStateList || []),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning (data loss): Dedup key is still `${city},${state}`. With richer address objects, two distinct streets in the same city/state will collapse. Worth a test or switching the key to fullAddress/streetAddress when those fields exist.

*/
function fullAddressStrings(value, separator) {
const lineBreakMarker = '\uE000';
const protectedValue = value.replace('\n', lineBreakMarker);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

info: Only the first is protected before list splitting. Multi-line addresses with several breaks may still split incorrectly when a custom separator is configured.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale comment

Injected PR Evaluation: Web Compatibility & Security

Re-assessed on synchronize (a9e792496). Latest commit updates an existing integration-test expectation to match the richer address profile — no runtime changes.

Web Compatibility Assessment

  1. injected/src/features/broker-protection/extractors/address.js (149–152)warning: formatStreetAddress() reassembles parsed components with normalized abbreviations (e.g. "street""St"). Opt-out forms that require verbatim page text may reject the filled value even when fullAddress preserves the original string.
  2. injected/src/features/broker-protection/actions/extract.js (391)warning: Address deduplication still keys on `${city},${state}`. With richer full-address objects, distinct streets in the same city/state collapse to one entry in addresses[].
  3. injected/src/features/broker-protection/extractors/address.js (136–139)info: fullAddressStrings() protects only the first before list splitting; additional newlines are collapsed via replace(/\s+/g, ' ') at parse time.
  4. injected/src/features/broker-protection/actions/fill-form.js (86–89)info: New street / zipCode field types fall back to generated values when data is missing (unlike cityState, which errors). Intentional for opt-out resilience, but a partial extraction could submit synthetic address data.
  5. No general web-compat regressions — Changes are scoped to broker-protection extract/fill logic on data-broker pages. No browser API overrides, prototype mutation, observers, or page-wide DOM side effects.

Security Assessment

  1. No security-critical path changes — No edits to captured-globals.js, wrapper utilities, message bridge, messaging transports, or origin validation.
  2. injected/src/features/broker-protection/actions/extract.js (116–122, 410–416)info: Extended scrape output (...parsed, top-level street/zipCode) flows through the existing SuccessResponse → native messaging path. Data is page-derived; no new exfiltration vectors beyond pre-existing broker-protection extraction.
  3. injected/src/features/broker-protection/actions/fill-form.js (86–89)info: Pre-existing setValueForInput uses uncaptured Object.getOwnPropertyDescriptor / Event (established autofill pattern). No new dynamic code execution, postMessage, or network requests.
  4. Messaging hygiene — No object spreading of unknown payloads; no nativeData in outgoing messages.

Risk Level

Low Risk — Broker-protection-only changes extending address extraction and form-fill field types, with solid unit/integration coverage and no API-override or security-boundary modifications.

Recommendations

  1. (warning) When configuring opt-out forms, prefer fullAddress (verbatim) over street/streetAddress if a broker validates against exact page text; document this in broker config guidance.
  2. (warning) Consider dedup keying on fullAddress or streetAddress when available, not just city,state, to avoid losing distinct addresses in the same locale.
  3. (info) Add a unit test for multi-line addresses with more than one if brokers emit that format.
  4. (info) Consider explicit error (not generated fallback) for street/zipCode when extraction is required for a given broker step.

Tests: 45/45 broker-protection extract + fill-form unit specs pass locally.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

noisysocks and others added 4 commits July 21, 2026 11:21
Preserve extracted street and ZIP data so broker opt-out forms can use real addresses while retaining generated fallbacks.

Co-authored-by: Cursor <[email protected]>
Add a sanitised broker-style fixture to verify the current full address is selected and retained end to end.

Co-authored-by: Cursor <[email protected]>
Keep the existing extraction fixture aligned with the richer address profile returned by the extractor.

Co-authored-by: Cursor <[email protected]>
Return a clean {streetAddress, city, state, zip, fullAddress} shape from
extractAddressFull instead of leaking all parse-address internals, and split
address lists by delimiter before collapsing intra-address whitespace (dropping
the newline-marker hack). Document the city/state dedup and the street/zipCode
generated fallback, and add an end-to-end opt-out form-fill integration test.
Fixture names follow the existing scenario-based convention (no broker name).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@noisysocks
noisysocks force-pushed the poc/people-search-now-address-anchor branch from a9e7924 to d6922e1 Compare July 21, 2026 02:04

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Web Compatibility Assessment

File Lines Severity Finding
injected/src/features/broker-protection/extractors/address.js 160–171 warning formatStreetAddress() rebuilds the street line from parse-address tokens, which normalizes abbreviations (e.g. "Street" → "St"). Brokers that validate opt-out forms against verbatim page text may reject the normalized value. fullAddress preserves the original string but is not used by fillForm today.
injected/src/features/broker-protection/actions/extract.js 391–395 warning Address deduplication still keys on ${city},${state} only. Multiple distinct streets in the same city/state collapse to one entry in addresses. Documented as acceptable for city/state matching, but the surviving entry may not be the user's actual street. Form fill is unaffected because currentAddress is taken from page order separately.
injected/src/features/broker-protection/extractors/address.js 144–157 info Default list separator for full addresses is `/[
injected/src/features/broker-protection/actions/fill-form.js 90–93 info street and zipCode fall back to generated values when extraction is empty (same pattern as existing $generated_*$ types). A generated street/zip that does not match the broker record could cause opt-out validation failure, but prevents leaving required fields blank.
injected/src/features/broker-protection/actions/extract.js 382–419 info No API overrides, prototype mutations, or global shims. Changes are confined to broker-protection extract/aggregate logic, which only runs when the feature is enabled and native schedules an action on a broker page.

Security Assessment

File Lines Severity Finding
injected/src/features/broker-protection/actions/extract.js 408–424 info New street/zipCode fields are explicitly constructed from scraped DOM text and returned to native via existing actionCompleted messaging. No nativeData forwarding; no new message schemas or bridge changes.
injected/src/features/broker-protection/actions/fill-form.js 90–93 info Page-derived address components are written into broker opt-out form fields — intentional, scoped behavior. Values pass through existing setValueForInput() (native setter + synthetic events); no new eval, postMessage, or network requests.
injected/src/features/broker-protection/extractors/address.js 120–134 info parse-address parses untrusted page text. Output is used only for broker opt-out automation, not for security decisions. Parsing failures are filtered by the parsed.city guard.
info No changes to captured-globals.js, message-bridge trust boundaries, origin validation, load()-time hooks, or shouldExemptMethod(). Pre-existing uncaptured Object.getOwnPropertyDescriptor / new Event() usage in fill-form.js is unchanged.

Risk Level

Low Risk — Broker-protection–scoped extraction and form-fill changes only; no browser API overrides, messaging security changes, or cross-site impact. Blast radius is limited to configured broker opt-out flows.

Recommendations

  1. (warning) Monitor PeopleSearchNow opt-out validation with normalized streetAddress values. If brokers reject abbreviated forms, consider a fullAddress-based fill type or a verbatim street-line extractor for the street field.
  2. (warning) Document the city/state dedup limitation in broker config guidance so operators know addresses is a match aid, not a complete history list.
  3. (info) If newline-separated address lists appear in the wild, add an explicit separator to the broker config or extend ADDRESS_LIST_SEPARATOR.
  4. (info) 48 broker-protection unit specs pass locally (broker-protection-extract.js, broker-protection-fill-form.js).
Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

*/
function formatStreetAddress(address) {
const unit = [address.sec_unit_type, address.sec_unit_num].filter(Boolean).join(' ');
const streetAddress = [address.number, address.prefix, address.street, address.type, address.suffix, unit].filter(Boolean).join(' ');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning (web compat): formatStreetAddress() normalizes tokens via parse-address (e.g. "Street" → "St"). If a broker's opt-out form validates against verbatim page text, this normalized value may be rejected even though fullAddress preserves the original. Consider exposing a verbatim street fill path if PeopleSearchNow validation fails in production.

// Deduped to one entry per city/state: this list is used for matching the user against a
// profile, which is a city/state-level comparison. The current address (with its street/zip) is
// flattened separately below, so collapsing same-city history here doesn't lose what fills a form.
const addressMap = new Map(combinedAddresses.map((addr) => [`${addr.city},${addr.state}`, addr]));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning (web compat): Dedup still keys on city,state only — distinct streets in the same city/state collapse to one addresses entry. Acceptable for city/state matching, but worth noting in broker config docs. Form fill is safe because currentAddress is sourced from page order above.

Add top-of-fixture comments noting the markup is a trimmed subset of a real
PeopleSearchNow page (matching the Veripages fixture convention), and replace
the real broker-record name with the standard Smith placeholder.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-minor New feature — triggers minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant