Commit graph

141 commits

Author SHA1 Message Date
aaac1f8f4b docs: fix ASCII architecture diagram alignment
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 8s
Mirror to GitHub / mirror (push) Failing after 5s
Tests / test (push) Successful in 23s
2026-03-23 14:17:41 +00:00
71b96598ed docs: refresh README — 11 engines, accurate clone URLs, API key clarity
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 5s
Tests / test (push) Successful in 22s
2026-03-23 14:07:49 +00:00
ba06582218 docs: add CONTRIBUTING guide for adding new engines
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 5s
Tests / test (push) Successful in 22s
Covers the full lifecycle: interface, SearchRequest/SearchResponse,
result building, graceful degradation, factory wiring, planner
registration, testing, and RSS parsing example.
2026-03-23 08:19:28 +00:00
1e81eea28e chore: remove stale design and implementation plan docs
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 5s
Tests / test (push) Successful in 22s
2026-03-23 08:10:15 +00:00
015f8b357a fix: rename remaining kafka references to samsa
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 5s
Tests / test (push) Successful in 26s
- OpenSearch description: 'Search results for "..." - kafka' → samsa
- Test error message: 'kafka trial' → samsa trial
2026-03-23 07:25:30 +00:00
8e9aae062b rename: kafka → samsa
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 11s
Mirror to GitHub / mirror (push) Failing after 5s
Tests / test (push) Successful in 42s
Full project rename from kafka to samsa (after Gregor Samsa, who
woke one morning from uneasy dreams to find himself transformed).

- Module: github.com/metamorphosis-dev/kafka → samsa
- Binary: cmd/kafka/ → cmd/samsa/
- CSS: kafka.css → samsa.css
- UI: all 'kafka' product names, titles, localStorage keys → samsa
- localStorage keys: kafka-theme → samsa-theme, kafka-engines → samsa-engines
- OpenSearch: ShortName, LongName, description, URLs updated
- AGPL headers: 'kafka' → 'samsa'
- Docs, configs, examples updated
- Cache key prefix: kafka: → samsa:
2026-03-22 23:44:55 +00:00
c91908a427 Merge commit 'df67492' 2026-03-22 23:41:36 +00:00
0030cf97ad feat: per-engine accent colors in search results
Each engine now has a distinctive color accent applied to its result
card (left border) and engine badge (colored left strip + text).

16 engines mapped to brand-appropriate colors:
Google blue, Bing teal, DDG orange-red, Brave red, Qwant blue,
Wikipedia dark, GitHub purple, Reddit orange-red, YouTube red,
Stack Overflow amber, arXiv crimson, Crossref navy blue.

Pure CSS via data-engine attribute — no JavaScript.
2026-03-22 22:59:32 +00:00
df67492602 feat: add Stack Overflow search engine
Uses the Stack Exchange API v3 (/search/advanced) to find questions
sorted by relevance. No API key required (300 req/day); optionally
configure via STACKOVERFLOW_KEY env var or [engines.stackoverflow].

Results include score, answer count, view count, and tags in the
snippet. Assigned to the 'it' category, triggered by the IT category
tab or explicit engine selection.

6 tests covering parsing, edge cases, and helpers.
2026-03-22 22:29:34 +00:00
e96040ef35 chore: remove React frontend, SPA server, and compiled binary
The project uses pure Go HTML templates + CSS. The React frontend
(frontend/), SPA handler (internal/spa/), and prebuilt binary (kafka)
were dead weight.

Also removes the frontend replacement plan/spec docs.
2026-03-22 22:18:19 +00:00
c97e6a6182 fix(frontend): improve pagination CSS for better centering and sizing
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 4s
Tests / test (push) Failing after 19s
- Match .page-current padding to button padding (0 0.75rem)
- Add box-sizing: border-box to buttons
- Add margin/padding reset to pagination forms
- Simplify page-current flex layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 23:14:48 +01:00
f92ec02dba fix: center page numbers in pagination
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 4s
Tests / test (push) Failing after 18s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 22:36:06 +01:00
a61a3a9c70 fix: improve pagination styling for active page and next button
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 18s
Match padding and sizing for active page number and next button
to match inactive page buttons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 22:31:53 +01:00
d7ec0217c4 feat: add settings link to header
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 18s
Add gear icon link to preferences page in the header.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 22:29:53 +01:00
77a41834a5 feat: add preferences page with theme toggle
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 18s
- Simple preferences page with engine selection
- Light/dark theme toggle with localStorage persistence
- Clean form layout without complex JS dependencies
- Add dark theme CSS variables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 22:27:48 +01:00
030b4a8508 feat: make search bar sticky on results page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 22:24:02 +01:00
23dcdef26f fix: unescape HTML entities in result titles
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 19s
Wikipedia returns HTML entities like &lt;span&gt; which were being
double-escaped by Go templates. Now using html.UnescapeString and
template.HTML to render properly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 22:19:07 +01:00
37420ae5a8 refactor(frontend): port search-zen-50 style to Go templates
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 18s
Replace React SPA with simple Go templates using search-zen-50
visual style. No JavaScript required - pure HTML/CSS with clean
teal accent color scheme, monospace logo, and minimal design.

- Simplified base.html without HTMX or autocomplete JS
- Clean homepage with centered search box
- Results page with sticky header and category tabs
- Simplified CSS matching search-zen-50 aesthetics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 22:05:56 +01:00
168cb78fab feat: add frontend source code
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 16s
Add search-zen-50 React SPA source code to frontend/ directory.
Build artifacts (dist, node_modules, lock files) are gitignored.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:27:45 +01:00
6b418057ef feat(frontend): replace Go templates with React SPA
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 16s
- Add internal/spa package for embedding React build
- Wire SPA handler in main.go for non-API routes
- Add gitignore entry for internal/spa/dist
- Add implementation plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:12:01 +01:00
5d14d291ca feat(main): wire SPA handler in main.go
Replace template-based handlers (h.Index, h.Preferences) with the new spa
handler. API routes (healthz, search, autocompleter, opensearch.xml) are
registered first as exact matches, followed by the SPA catchall handler
for all other routes. Remove unused views and io/fs imports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 19:50:03 +01:00
8651183540 feat(spa): add SPA Go package with embedded dist FS
Creates internal/spa package that:
- Embeds React build output from cmd/kafka/dist/
- Provides HTTP handler for static file serving
- Falls back to index.html for SPA client-side routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 19:40:34 +01:00
1543b16605 docs: add frontend replacement design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 18:58:50 +01:00
00b2be9e79 fix(css): restore original layout, re-add only image grid styles
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 24s
Reverted CSS to the known-working state at 4b0cde9, then re-applied
only the image grid styles. The duplicate .results-layout block is
intentional — it was present in the working version too.
2026-03-22 17:35:35 +00:00
2f10f4e1e5 fix(css): remove duplicate .results-layout that broke 3-column grid
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 22s
The old 3-column layout block (referencing .left-sidebar/.right-sidebar
classes that don't exist in the HTML) was overriding the correct layout
defined earlier. Removed the stale duplicate.
2026-03-22 17:31:06 +00:00
a9ae69cad5 fix(security): allow HTMX CDN and inline scripts in CSP
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 8s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 22s
script-src now permits 'unsafe-inline' and https://unpkg.com so the
autocomplete script and HTMX library load correctly.
2026-03-22 17:22:31 +00:00
2b072e4de3 feat: add image search with Bing, DuckDuckGo, and Qwant engines
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 25s
Three new image search engines:
- bing_images: Bing Images via RSS endpoint
- ddg_images: DuckDuckGo Images via VQD API
- qwant_images: Qwant Images via v3 search API

Frontend:
- Image grid layout with responsive columns
- image_item template with thumbnail, title, and source metadata
- Hover animations and lazy loading
- Grid activates automatically when category=images

Backend:
- category=images routes to image engines via planner
- Image engines registered in factory and engine allowlist
- extractImgSrc helper for parsing thumbnail URLs from HTML
- IsImageSearch flag on PageData for template layout switching
2026-03-22 16:49:24 +00:00
a316763aca fix(test): update CORS preflight test for deny-all default
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 24s
Empty CORSConfig now means no CORS headers, matching the security fix.
Test explicitly configures an origin to test preflight behavior.
2026-03-22 16:38:03 +00:00
5884c080fd Merge branch 'security/hardening-sast-fixes'
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Failing after 19s
2026-03-22 16:31:57 +00:00
b3e3123612 security: fix build errors, add honest Google UA, sanitize error msgs
- Fix config validation: upstream URLs allow private IPs (self-hosted)
- Fix util.SafeURLScheme to return parsed URL
- Replace spoofed GSA User-Agent with honest Kafka UA
- Sanitize all engine error messages (strip response bodies)
- Replace unused body reads with io.Copy(io.Discard, ...) for reuse
- Fix pre-existing braveapi_test using wrong struct type
- Fix ratelimit test reference to limiter variable
- Update ratelimit tests for new trusted proxy behavior
2026-03-22 16:27:49 +00:00
da367a1bfd security: harden against SAST findings (criticals through mediums)
Critical:
- Validate baseURL/sourceURL/upstreamURL at config load time
  (prevents XML injection, XSS, SSRF via config/env manipulation)
- Use xml.Escape for OpenSearch XML template interpolation

High:
- Add security headers middleware (CSP, X-Frame-Options, HSTS, etc.)
- Sanitize result URLs to reject javascript:/data: schemes
- Sanitize infobox img_src against dangerous URL schemes
- Default CORS to deny-all (was wildcard *)

Medium:
- Rate limiter: X-Forwarded-For only trusted from configured proxies
- Validate engine names against known registry allowlist
- Add 1024-char max query length
- Sanitize upstream error messages (strip raw response bodies)
- Upstream client validates URL scheme (http/https only)

Test updates:
- Update extractIP tests for new trusted proxy behavior
2026-03-22 16:22:27 +00:00
4b0cde91ed feat: 3-column layout with centered results and right column
- results-layout: 3-column grid (1fr | min(768px,100%) | 300px) max-width 1400px, centered
- Widen center results column to 768px max
- Right column (formerly sidebar): sticky, contains knowledge panel + related searches
- Knowledge panel: Wikipedia/infobox summary with optional thumbnail
- Related searches: clickable links to refine the query
- Empty left buffer creates balanced whitespace on large screens
- Responsive: 2-col at 1000px, 1-col at 700px
2026-03-22 16:01:49 +00:00
2d22a8cdbb feat: add Brave web search scraper engine
New brave.go: scrapes https://search.brave.com directly.
Extracts title, URL, snippet, and favicon from Brave's HTML.
No API key required.

Rename existing BraveAPIEngine (was BraveEngine) to avoid collision
with the new scraper. API engine stays as 'braveapi', scraper as 'brave'.
2026-03-22 16:01:49 +00:00
994d27ff7f fix(flake): set correct vendorHash
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 27s
The correct vendorHash for current go.mod is:
sha256-8wlKD+33s97oorCJTfHKAgE2Xp1HKXV+bSr6z29KrKM=

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 15:17:03 +00:00
e2ff822847 fix(flake): set vendorHash to auto-compute
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 21s
The go.mod was updated with new replace directive for golang.org/x/net.
Need to recompute vendorHash.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:05:28 +00:00
0b381c001f fix(flake): simplify preConfigure
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 7s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 21s
2026-03-22 13:28:32 +00:00
7969b724de fix(engines): remove unsupported lookahead from Google regex
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6s
Mirror to GitHub / mirror (push) Failing after 3s
Tests / test (push) Successful in 41s
Go's regexp package doesn't support Perl lookahead (?=...). Removing
the unnecessary lookahead since each MjjYud div is self-contained.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:16:04 +01:00
cdfdb16c26 Merge branch 'worktree-brave-search-redesign' 2026-03-22 14:09:29 +01:00
0402d249b8 Merge branch 'main' of https://github.com/metamorphosis-dev/kafka 2026-03-22 14:09:29 +01:00
e18a54a41a fix(frontend): add HTMX filter submission for sidebar radio buttons
Wrap sidebar time/type filters in a form with HTMX attributes so
filter changes trigger partial page updates instead of full reload.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:05:26 +01:00
6d7e68ada1 feat(frontend): reduce popover to theme+engines, add preferences page JS 2026-03-22 14:00:53 +01:00
0afcf509c3 fix: use single Preferences handler with method check instead of dead POST route 2026-03-22 13:57:32 +01:00
70818558cd feat: add GET and POST /preferences route
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:53:23 +01:00
b4053b7f98 feat(frontend): add preferences page template and styles
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:47:30 +01:00
3dbde9fbfd feat(frontend): add category tiles to homepage 2026-03-22 13:42:24 +01:00
bfcbd45c57 fix(frontend): update FromResponse tests and fix disabled categories rendering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:40:16 +01:00
0e79b729fe feat(frontend): add three-column results layout with left sidebar navigation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:36:09 +01:00
2e7075adf1 fix(frontend): merge duplicate sidebar sticky rules 2026-03-22 13:33:24 +01:00
0af49f91b7 feat(frontend): add CSS layout framework for three-column results and preferences page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:29:39 +01:00
d071921329 docs: add missing template registration step to plan
- Add tmplPreferences variable to views.go var block
- Initialize tmplPreferences in init() function
- Add RenderPreferences function to views.go
- Fix step numbering for Task 4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:26:22 +01:00