feat(server): learn personalized ranking from served-page clicks (Android A2)#50
Merged
Merged
Conversation
…roid A2) Add an owner-only `/click` redirect so searches run from the browser through the local server also train the personalization model, matching the native app and the desktop app's D2. - server/SearchServer.kt: a loopback-only `GET /click?rid=..&pos=..` route. The server remembers each owner render (a fresh unguessable id -> the displayed (url, host) order) in a small, bounded, in-memory map, and `/click` resolves the destination from that server state, never a caller-supplied URL. So it cannot be an open redirect, a network client gets 404 and cannot forge a rid, and a stale rid / bad pos falls back to home. It trains the model (Personalizer.updateFromClick) then 302s. - Owner result links route through `/click` only when personalization is on (a new renderResultsPage linkBuilder); everyone else gets plain links. - Wire personalizationPreferences + the enabled flag through SearchServer and SearchMobService. - Add the add-click-personalization OpenSpec change (proposal/design/specs/ tasks) for the whole feature; `openspec validate --strict` passes. Gate green: ktlint, lint, testDebugUnitTest (new ClickRouteTest), assemble. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
A2 of the Android click-personalization feature: an owner-only
/clickredirector so searches run from the browser (through the local server) also train the model, matching the native app (A1, merged in #48) and the desktop app's D2. Also lands theadd-click-personalizationOpenSpec change for the whole feature (the repo's CONTRIBUTING requires it; it was deferred in A1).How it stays safe
GET /click?rid=..&pos=..is loopback-only (a non-owner gets404).rid→ the displayed(url, host)order) in a small, bounded, in-memory map (never persisted)./clickresolves the destination from that server state, never a caller-supplied URL, so it cannot be an open redirect and a network client cannot forge arid.ridor badposfalls back to/and learns nothing./clickonly when personalization is on (a newrenderResultsPagelinkBuilder); everyone else (and a disabled owner) gets the plain destination link.Personalizer.updateFromClick, then302s. Persisted to the encrypted store; only when the feature is enabled.Tests
ktlint+lint+assembleDebug+ unit tests green. NewClickRouteTeston the real-loopback harness: owner records the skip-above update + redirects to the right URL; disabled owner gets plain links; forged/staleridand badposfail safe. Network refusal stays covered by theisLoopbackHostunit tests + the handler'sisOwnerRequest404 gate.openspec validate add-click-personalization --strictpasses.🤖 Generated with Claude Code