Skip to content

feat(search): Google-style search operators, server security hardening, Material 3 web UI#96

Merged
ErikChevalier merged 3 commits into
mainfrom
claude/search-modifiers-material-ui-lv3vpe
Jul 2, 2026
Merged

feat(search): Google-style search operators, server security hardening, Material 3 web UI#96
ErikChevalier merged 3 commits into
mainfrom
claude/search-modifiers-material-ui-lv3vpe

Conversation

@ErikChevalier

Copy link
Copy Markdown
Contributor

What & why

Three related upgrades to the search pipeline and the served (loopback/network) web UI, so SearchMob queries work like the major engines' do:

Google-fu search operators (engine layer). A new pure QueryOperators parser supports "exact phrase", -term, -"phrase", site: / -site: (incl. .edu-style TLD entries and *.host normalization), intitle: / -intitle:, inurl: / -inurl:, filetype: / ext:, before: / after: (YYYY, YYYY-MM, YYYY-MM-DD, YYYY/MM/DD, UTC), and OR / |. Operators the upstream engines understand are forwarded in original token order; the rest become bare recall hints or are dropped, and every structural filter is additionally enforced on-device over the aggregated results, so behavior is consistent even for engines that ignore an operator. The operator-free text now drives lexical relevance (fixing a pre-existing issue where a vertical's site: OR-group polluted relevance scoring), sorting, personalization, the Wikipedia summary lookup, and the spell corrector (skipped for operator-laden queries). Works identically in-app and on the served page.

Security fixes (served pages).

  • Fixed a CSRF bypass: a literal Origin: null was treated as same-origin, but an attacker page can forge exactly that (its own Referrer-Policy: no-referrer, or a sandboxed iframe) on a cross-site POST to the loopback server. Origin: null / unparseable origins are now rejected, and the server serves Referrer-Policy: same-origin so its own form posts carry a real origin (cross-origin still leaks nothing; result links keep rel="noreferrer").
  • Added Content-Security-Policy (default-src 'none', form-action 'self', frame-ancestors 'none', …), Cache-Control: no-store, and Permissions-Policy on every response.
  • The network-mode access token is now compared in constant time (MessageDigest.isEqual) and can be presented via Authorization: Bearer or X-SearchMob-Token headers, not just the history-leaking ?token= query parameter (which stays for OpenSearch templates).

Material 3 web UI. The served pages are restyled to Material 3: elevated 28px search bar with focus/hover states, 16px-radius cards, pill buttons, chip state layers (color-mix() with plain fallbacks declared first), theme-derived active-tab colors replacing hardcoded hex, extended focus-visible rings, and a collapsible "Search operators" cheat sheet under the home search box. All theme-registry CSS variables and test-pinned markup kept intact. (The Android GUI is already Compose Material 3 and was intentionally left alone.)

Relates to OpenSpec change: n/a (no OpenSpec change directory in this repo)

Checklist

  • Built on its own feat//fix/ branch off main
  • ./gradlew ktlintCheck lint test assembleDebug is green locally — the sandbox cannot reach dl.google.com/the Gradle distribution, so this relies on CI; the new/changed pure-JVM engine code was compiled and its 47 new unit tests run green with a standalone Kotlin 2.4.0 compiler, and ktlint (CLI) reports no new findings vs. main
  • Added/updated tests (unit and/or instrumentation): 43 parser tests, 4 provider integration tests, security-header/CSRF/token tests, operators-help markup test; flipped the test that pinned the vulnerable Origin: null behavior
  • No telemetry, trackers, or device identifiers added
  • No Google scraping introduced
  • Battery: no wake-lock held while idle
  • OpenSpec change validates (openspec validate <name> --strict) and tasks are checked off — n/a

🤖 Generated with Claude Code

https://claude.ai/code/session_016AYAgNYmBkxsEYcgzSAjgT


Generated by Claude Code

claude added 3 commits July 2, 2026 09:50
…forced on-device

Adds a pure QueryOperators parser for "exact phrase", -term, -"phrase",
site:/-site:, intitle:/-intitle:, inurl:/-inurl:, filetype:/ext:,
before:/after: (YYYY[-MM[-DD]] and YYYY/MM/DD), and OR/|.

Operators the upstream engines understand (quotes, exclusions, site:,
filetype:, OR) are forwarded in original token order; the rest become
recall hints or are dropped, and every structural filter is enforced
locally over the aggregated results so behavior is consistent across
engines that ignore an operator. The operator-free text now drives
lexical relevance (a vertical's site: clause no longer pollutes it),
sorting, personalization, the contextual summary, and the on-device
spell corrector (skipped for operator-laden queries).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016AYAgNYmBkxsEYcgzSAjgT
…ening

Security: reject the forgeable 'Origin: null' on mutation POSTs (a page
setting its own no-referrer policy, or a sandboxed iframe, could forge
it and bypass the CSRF guard) and serve Referrer-Policy: same-origin so
our own form posts carry a real origin; add Content-Security-Policy,
Cache-Control: no-store, and Permissions-Policy on every response; make
the network-mode token comparison constant-time and accept the token
via Authorization: Bearer or X-SearchMob-Token headers in addition to
the ?token= query parameter.

UI: restyle the served pages to Material 3 (search-bar elevation and
focus states, 16px-radius cards, pill buttons, chip and state-layer
hovers with plain fallbacks, theme-derived active-tab colors instead of
hardcoded hex) and add a collapsible search-operators cheat sheet under
the home search box.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016AYAgNYmBkxsEYcgzSAjgT
@ErikChevalier ErikChevalier marked this pull request as ready for review July 2, 2026 10:24
@ErikChevalier ErikChevalier merged commit df60723 into main Jul 2, 2026
2 checks passed
@ErikChevalier ErikChevalier deleted the claude/search-modifiers-material-ui-lv3vpe branch July 2, 2026 10:24
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.

2 participants