|
|
89d3862f62
|
feat(monitor): background saved-search monitoring with watch alerts (#12)
CI / Python tests (push) Has been cancelled
CI / Frontend typecheck + tests (push) Has been cancelled
Mirror / mirror (push) Has been cancelled
Release / release (push) Has been cancelled
Backend:
- Migrations 013-015: eBay user tokens, monitor settings on saved_searches
(monitor_enabled, poll_interval_min, min_trust_score, last_checked_at),
watch_alerts table with UNIQUE dedup on (saved_search_id, platform_listing_id),
active_monitors registry for cross-user polling
- WatchAlert model + store methods: upsert_alert, list_alerts, dismiss_alert,
count_undismissed_alerts, dismiss_all_alerts, list_active_monitors
- monitor.py: run_monitor_search() using TrustScorer.score_batch(); should_alert()
with BIN/auction/partial-score logic (auction window = 24h, partial +10 buffer)
- PATCH /api/saved-searches/{id}/monitor, GET /api/alerts, POST /api/alerts/*/dismiss
- Background polling loop at startup (asyncio.to_thread every 60s check cycle)
- ebay/adapter.py: enrich_seller_trading_api() via Trading API GetUser (OAuth token)
- nginx: raise proxy_read_timeout to 120s for slow eBay search responses
Frontend:
- AlertBell component: bell button + unread badge + panel with dismiss/clear-all;
polls /api/alerts every 2 minutes; aria-live announcement on count change
- alerts.ts Pinia store: fetchAlerts, dismiss, dismissAll
- SavedSearchesView: monitor toggle + poll interval + min trust score controls
- SettingsView: eBay OAuth connect/disconnect section
- AppNav: AlertBell wired for logged-in and local-tier users
Tests: 24 monitor tests (should_alert branches, store alert CRUD, run_monitor_search
with mocked adapter); fix browser_pool test assertions for new wait_for_* params.
|
2026-05-04 08:24:56 -07:00 |
|
|
|
e93e3de207
|
feat: scammer blocklist, search/listing UI overhaul, tier refactor
**Scammer blocklist**
- migration 006: scammer_blocklist table (platform + seller_id unique key,
source: manual|csv_import|community)
- ScammerEntry dataclass + Store.add/remove/list_blocklist methods
- blocklist.ts Pinia store — CRUD, export CSV, import CSV with validation
- BlocklistView.vue — list with search, export/import, bulk-remove; sellers
show on ListingCard with force-score-0 badge
- API: GET/POST/DELETE /api/blocklist + CSV export/import endpoints
- Router: /blocklist route added; AppNav link
**Migration renumber**
- 002_background_tasks.sql → 007_background_tasks.sql (correct sequence
after blocklist; idempotent CREATE IF NOT EXISTS safe for existing DBs)
**Search + listing UI overhaul**
- SearchView.vue: keyword expansion preview, filter chips for condition/
format/price, saved-search quick-run button, paginated results
- ListingCard.vue: trust tier badge, scammer flag overlay, photo count
chip, quick-block button, save-to-search action
- savedSearches store: optimistic update on run, last-run timestamp
**Tier refactor**
- tiers.py: full rewrite with docstring ladder, BYOK LOCAL_VISION_UNLOCKABLE
flag, intentionally-free list with rationale (scammer_db, saved_searches,
market_comps free to maximise adoption)
**Trust aggregator + scraper**
- aggregator.py: blocklist check short-circuits scoring to 0/BAD_ACTOR
- scraper.py: listing format detection, photo count, improved title parsing
**Theme**
- theme.css: trust tier color tokens, badge variants, blocklist badge
|
2026-04-03 19:08:54 -07:00 |
|
|
|
98695b00f0
|
feat(snipe): eBay trust scoring MVP — search, filters, enrichment, comps
Core trust scoring:
- Five metadata signals (account age, feedback count/ratio, price vs market,
category history), composited 0–100
- CV-based price signal suppression for heterogeneous search results
(e.g. mixed laptop generations won't false-positive suspicious_price)
- Expanded scratch/dent title detection: evasive redirects, functional problem
phrases, DIY/repair indicators
- Hard filters: new_account, established_bad_actor
- Soft flags: low_feedback, suspicious_price, duplicate_photo, scratch_dent,
long_on_market, significant_price_drop
Search & filtering:
- Browse API adapter (up to 200 items/page) + Playwright scraper fallback
- OR-group query expansion for comprehensive variant coverage
- Must-include (AND/ANY/groups), must-exclude, category, price range filters
- Saved searches with full filter round-trip via URL params
Seller enrichment:
- Background BTF /itm/ scraping for account age (Kasada-safe headed Chromium)
- On-demand enrichment: POST /api/enrich + ListingCard ↻ button
- Category history derived from Browse API categories field (free, no extra calls)
- Shopping API GetUserProfile inline enrichment for API adapter
Market comps:
- eBay Marketplace Insights API with Browse API fallback (catches 403 + 404)
- Comps prioritised in ThreadPoolExecutor (submitted first)
Infrastructure:
- Staging DB fields: times_seen, first_seen_at, price_at_first_seen, category_name
- Migrations 004 (staging tracking) + 005 (listing category)
- eBay webhook handler stub
- Cloud compose stack (compose.cloud.yml)
- Vue frontend: search store, saved searches store, ListingCard, filter sidebar
Docs:
- README fully rewritten to reflect MVP status + full feature documentation
- Roadmap table linked to all 13 Forgejo issues
|
2026-03-26 23:37:09 -07:00 |
|
|
|
7a704441a6
|
feat(snipe): Vue 3 frontend scaffold + Docker web service
- web/: Vue 3 + Vite + UnoCSS + Pinia, dark tactical theme (amber/#0d1117)
- AppNav, ListingCard, SearchView with filters/sort, composables
(useSnipeMode, useKonamiCode, useMotion), Pinia search store
- Steal shimmer, auction countdown, Snipe Mode easter egg all native in Vue
- docker/web/: nginx + multi-stage Dockerfile (node build → nginx serve)
- compose.yml: api (8510) + web (8509) services
- Dockerfile CMD updated to uvicorn for upcoming FastAPI layer
- Clean build: 0 TS errors, 380 modules
|
2026-03-25 15:11:35 -07:00 |
|