Commit Graph

6 Commits

Author SHA1 Message Date
prosolis
7c95e4fd4e Add Authentik SSO, budget visibility, Resend email, 12h item default
Opens Veola up to more users (Parodia's Authentik) and makes Apify spend
visible to everyone.

- Auth: Traefik forward-auth (trust X-Authentik-* headers only from
  trusted_proxies CIDRs, keyed by email, role synced from admin_group),
  keeping local password login as break-glass. New [auth] config,
  CaptureDirectIP + ForwardAuth middleware, deploy/authentik-forward-auth.md.
- Budget: count every Apify run (apify_api_usage table) and show
  calls + estimated cost to all users on the dashboard, with an optional
  monthly-budget bar. New [budget] config + settings.
- Email: Resend client for opt-in deal alerts and a weekly digest
  (Mon 09:00). Per-user email + toggles on Settings. New [resend] config.
- Defaults: new items default to a 12-hour poll interval to cut spend.

users table gains email/auth_source/email-pref columns (migrated in place).
go build/vet/test green; boots and migrates cleanly.
2026-06-20 11:12:11 -07:00
prosolis
c173543aa3 Drop ended zenmarket auctions with unparsed end times
ExcludeEnded kept NULL ends_at rows on the fixed-price assumption, but
yahoo-auctions-jp is auction-only — a NULL there just means the actor's
ending_date didn't parse. Treat those as ended.
2026-05-18 22:38:31 -07:00
prosolis
ea3577a45e Items-list sparklines, retro CSS, pinned tooling, deploy docs
- Bulk-load recent price points per item and render a sparkline in
  the items list (new LoadRecentPriceHistory query avoids N+1).
- Add retro.css visual layer and refreshed login/items/layout styling.
- Swap the logo from webp to avif.
- Pin htmx/Chart.js/Tailwind/templ versions in the Makefile with
  vendor / tools / update-deps targets; README documents the
  dependency-bump flow and the hardened systemd deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 19:10:56 -07:00
prosolis
edb732ee1f Auction end times, visual flair, and pre-launch cleanup
Auction handling:
- Capture itemEndDate from eBay Browse API and ending_date from ZenMarket
  (Yahoo JP); plumb through results.ends_at column. Permissive ZenMarket
  parser (multiple layouts, JST when offset missing).
- Per-row "Ends" countdown column + "Ending soon" banner on results pages,
  live-ticked by flair.js with urgent/critical tinting under 1h/5m.
- Backfill ends_at for known auctions when their URL reappears in a poll
  (dedup hit no longer drops the new end time).
- Hide ended auctions from result listings by default via
  ResultsQuery.ExcludeEnded; rows stay in the DB.

Visual flair:
- Glassy backdrop-blur v-cards with gradient-mask borders and hover-lift.
- htmx swap fade-in via transient .v-just-swapped class.
- Count-up animation on dashboard stats. All animations gated behind
  prefers-reduced-motion.

eBay condition + region filters (auctions-style scoping):
- items.condition and items.region columns; threaded through item form,
  CreateItem/UpdateItem, scheduler eBay plan input, and previewKey so
  cache invalidates when these change.
- ebay.SearchParams gains conditionIds and itemLocationCountry filters.

Run Now reload + countdown engine:
- Run Now now sets HX-Refresh: true (non-htmx fallback: 303 redirect) so
  the entire results view — best price, chart, badge, last polled —
  reflects the new poll, instead of swapping just one partial.

Pre-launch hardening (P1 set):
- auth.EqualizeLoginTiming on no-such-user branch.
- (*App).serverError centralizes 500s; replaces err.Error() leaks across
  results/settings/items/users/dashboard handlers.
- main.go server: ReadTimeout 30s / WriteTimeout 60s / IdleTimeout 120s
  alongside the existing ReadHeaderTimeout.
- noListFS wrapper blocks static directory listings.
- Credential fields in settings no longer render value=; blank submission
  preserves the saved value, with per-field "Saved in settings / Set in
  config.toml / Not set" status indicator.

Misc:
- -debug flag wires slog to LevelDebug; raw ZenMarket items logged for
  format diagnosis.
- /healthz public endpoint for reverse-proxy probes.
- deploy/veola.service systemd unit template (hardening flags, single
  ReadWritePaths=/var/lib/veola).
- handlers_test.go covers /healthz, setup-gate redirect, auth gate, and
  /login render with httptest + in-memory sqlite.
- best_price_currency on items; templates pick the right symbol per row.
- .gitignore now excludes *.log / veola-debug.log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:47:09 -07:00
prosolis
1ae2c50b9a Add eBay Browse API integration with daily call quota
eBay marketplaces are now polled through eBay's official Buy > Browse API (client-credentials OAuth2) instead of an Apify scraper actor; Apify still handles Yahoo JP and Mercari. Browse API calls are tracked per day in a new ebay_api_usage table and capped (default 5000, configurable) on eBay's Pacific-time reset clock, so polling halts before the limit is hit. Credentials live in config.toml [ebay] and are overridable via /settings, which also surfaces the day's running call count.

Also carries the server.secure_cookies config plumbing (field, accessor, example) consumed by the following commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:10:39 -07:00
cfa01bd4ef Initial commit 2026-05-13 19:42:49 -07:00