Commit Graph
13 Commits
Author SHA1 Message Date
jozamudi 778bf2bfc1 status: consolidate CDN/upstream status into the header pill + tap panel
- pill label now shows KB/s when degraded ('cdn 23 KB/s'); tap opens a
  panel (replaces the transient toast) with origin/CDN state, KB/s,
  a sparkline of the ~1h /api/cdn hist, and last-updated age
- 60s poll while the page is visible (was: load/play/failure only)
- playback failure overlay appends CDN context when degraded/down
- buffer gauge + spinner untouched: client buffer state, not CDN state
- server unchanged: /api/cdn already returned everything
- tests: 3 hermetic browser tests (mocked /api/cdn via page.route —
  the throwaway server's probe runs live upstream, so its data is
  mocked out of the assertions); 37 passed
- docs: README + SPEC synced
2026-09-20 23:53:47 +00:00
jozamudi 816e945018 docs: slim README to what it uniquely owns (run, features, dev commands); implementation detail already lived in SPEC.md — moved the two stragglers (anidb self-check, cache-busting) over 2026-09-20 23:34:32 +00:00
jozamudi 0f6bd0a52a docs: sync README + SPEC with the shipped reality
Both docs still described the pre-provider-layer single-source app:

- README: anidb-only framing, missing stats page, 'upstream.py is the
  ONLY Cloudflare-facing code', and a self-check command that does not
  work (plain script execution breaks the providers' relative imports;
  the asserts are anidb-specific under the hianime-first default) —
  now documents ANI_SOURCE=anidb + the -m form. Dropped the stale
  'episode titles are not available' note (Jikan titles shipped).
- SPEC: 'no database' -> SQLite, architecture -> 3 providers, full
  endpoint list (intros/searches/events/stats/cdn, DELETE history,
  ?all=1, {sub}), auth hardening (per-IP budget, X-Aniweb on /login),
  tests/run.py -> pytest + ANIWEB_LIVE_TESTS gating, out-of-scope list
  (countdown/intro-skip/titles shipped), risks updated for the
  fallback layer, milestone 8 pointer.
2026-09-16 21:14:26 +00:00
jozamudi d02cb017d3 gate live-upstream browser e2e behind ANIWEB_LIVE_TESTS=1: provider rotation/takedowns were turning the suite red for non-regressions; default suite is hermetic (33 tests) again 2026-09-16 02:41:25 +00:00
jozamudi 14bdb04ef6 Docs: sync with reality
README: storage is SQLite (aniweb.db), not JSON files; CDN serves a
single quality (no ABR) — replaced the wrong 1080/720/360 claim;
document the 16-lane parallel fetch, intro-skip, episode names,
buffering UI, /api/cdn + background probe, the ?v= cache-busting rule,
and the client self-report diagnostics.
SPEC: same single-rendition correction (2 places).
PLAN: marked complete (all items shipped; deferred list was stale).
2026-09-01 21:25:13 +00:00
jozamudi d6bf7e149b docs: README feature walkthrough with screenshots; css: .active wins over .nextup 2026-08-19 20:23:39 +00:00
jozamudi 2ec0f8a034 ui: loading states, player failure overlay + retry, toasts, back nav, full history page with delete
Bundle 1-4+7 from PLAN.md: skeleton loaders, player Loading/Buffering/fatal overlay with Retry, action toasts, back-to-home crumb + logo fix, ?history full-history view with per-entry delete (GET /api/history?all=1, DELETE /api/history). 14/14 tests green.
2026-08-19 18:20:42 +00:00
jozamudi 19e878800c perf: keep-alive upstream sessions, TTL cache on upstream data, /stream LRU, cache hls.min.js
- shared thread-local curl_cffi sessions (no TLS handshake per call)
- in-memory TTL cache: search 5min, details/episodes/languages/
  playlist-URLs 1h; api_stream retries once with a cold cache on 502
  (recovers rotated playlist URLs)
- /stream LRU (24 entries) serves re-seeks and playlist re-fetches from memory
- hls.min.js: Cache-Control public max-age=30d (was no-store -> 500KB
  re-download per page load on mobile)

Measured (click->play chain, cold -> warm):
  search    0.45s -> 0.00s
  detail    0.46s -> 0.00s
  episodes  0.40s -> 0.00s
  stream    1.06s -> 0.00s
  m3u8 x2   0.64s -> 0.00s
  segment   0.20s -> 0.00s
2026-08-19 17:46:17 +00:00
jozamudi f0f8207cf7 docs: README/SPEC current — multi-user, CLI accounts, Secure cookie, tests
- README: per-user history (was shared history.json), proxy/HTTPS
  access note, ANIWEB_SECURE, layout lists users.py + tests/ +
  login.html; merged duplicate history bullets
- SPEC: session hardening (Secure flag, per-request account
  existence check), run steps include account creation + test suite,
  milestone 7 (auth), fixed corrupted out-of-scope tail
2026-08-19 16:32:33 +00:00
jozamudi cdb25b1aba security: Secure cookie flag (ANIWEB_SECURE, on in run.sh) + kill sessions of deleted accounts
- middleware re-verifies the username against users.json per request:
  deleted accounts' signed cookies are rejected immediately
- set_cookie/delete_cookie honor the Secure flag; run.sh sets
  ANIWEB_SECURE=1 so sessions only work through the HTTPS proxy
2026-08-19 16:29:03 +00:00
jozamudi c697500c7d multi-user auth (CLI-created accounts), per-user history, test suite
- server/users.py replaces credentials.py: users.json (0600), PBKDF2,
  one-time migration of the legacy single password to user admin
  (history.json -> history/admin.json)
- accounts are CLI-managed only: python -m server.users add|rm|list
  (no self-signup on an internet-exposed app); /signup route removed,
  login page back to username + password
- per-user 30-day signed session cookie (payload carries the
  username), per-user lockout, GET /api/me, POST /account/delete
- per-user watch history: server/data/history/<user>.json; ANIWEB_DATA
  env override for the data dir
- header chip: logged-in user, logout, delete account
- tests/: throwaway-server suite (port 8399, temp data dir) — 9 HTTP
  tests + 2 Playwright browser tests (login UI, real video playback
  behind auth); runs via python tests/run.py
2026-08-19 16:17:56 +00:00
jozamudi 76c45a8f29 single-user login screen
- server/credentials.py: PBKDF2 password + session secret, 0600 json,
  one-time setup command (server refuses to start without it)
- app.py: signed 30-day cookie (itsdangerous), middleware 401s API /
  redirects pages to /login?next=, 5-fail/15-min lockout, /logout
- static/login.html: dark-themed form, inline error display
- app.js: api() 401 -> redirect to /login preserving current URL
- docs: README quick start + features, SPEC auth section
2026-08-19 15:54:50 +00:00
jozamudi 2c203990bc move server code into server/, update docs
- app.py + upstream.py -> server/ (relative import, __init__.py)
- static/ resolved relative to repo root, works from any CWD
- watch history migrated to server/data/history.json
- README.md: quick start, features, layout, dev notes
- SPEC.md: marked implemented, updated endpoints/run/deviations
- ignore *.tar.gz (local curl-impersonate download at repo root)
2026-08-19 15:33:31 +00:00