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.
20 lines
866 B
SQL
20 lines
866 B
SQL
-- Migration 013: eBay user OAuth tokens
|
|
--
|
|
-- Stores per-user eBay Authorization Code tokens so the app can call
|
|
-- Trading API GetUser for instant account_age_days + category feedback
|
|
-- without Playwright scraping.
|
|
--
|
|
-- Stored in the per-user DB (user.db), never the shared DB.
|
|
-- access_token is short-lived (2h); refresh_token is valid 18 months.
|
|
-- The API layer refreshes access_token automatically before expiry.
|
|
|
|
CREATE TABLE IF NOT EXISTS ebay_user_tokens (
|
|
id INTEGER PRIMARY KEY,
|
|
-- Single row per user DB — upsert on reconnect
|
|
access_token TEXT NOT NULL,
|
|
refresh_token TEXT NOT NULL,
|
|
expires_at REAL NOT NULL, -- epoch seconds; access token expiry
|
|
scopes TEXT NOT NULL DEFAULT '',
|
|
connected_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
last_refreshed TEXT
|
|
);
|