Commit Graph

  • f256f587ee Merge pull request 'UI batch + I1–I6 service passes + download-event recovery sweep' (#33) from dev into main bvandeusen 2026-05-29 22:46:16 -04:00
  • e35fb1edf7 fix(scan): recovery sweep for stranded download events bvandeusen 2026-05-29 21:40:52 -04:00
  • 08420cd619 feat(I6): FE/BE enum contract test — pin JS mirrors to backend canon bvandeusen 2026-05-29 15:34:20 -04:00
  • 8649a13118 refactor(I5): remove one-and-done GS/IR migration tooling bvandeusen 2026-05-29 14:38:59 -04:00
  • 8979e0e377 refactor(I4): extract useInfiniteScroll composable; migrate 6 consumers bvandeusen 2026-05-29 14:03:49 -04:00
  • 00e2608ba1 feat(I3): always-on pipeline status indicator in the top nav bvandeusen 2026-05-29 13:24:11 -04:00
  • 9ab5d709c8 fix(test): DownloadEventRow row shows platform, not artist name bvandeusen 2026-05-29 13:16:33 -04:00
  • 44410db492 test(I2): vitest component smoke tests for high-risk UI bvandeusen 2026-05-29 12:34:58 -04:00
  • e76aa36a29 ci(I1): dedicated fast-fail ruff lint lane bvandeusen 2026-05-29 12:22:33 -04:00
  • c95b760294 feat(posts): in-context anchored feed with bidirectional infinite scroll bvandeusen 2026-05-28 21:12:18 -04:00
  • 35fe420701 feat(maintenance): live queue-depth bar under the backfill buttons bvandeusen 2026-05-28 20:03:32 -04:00
  • 9e74c80e2f feat(downloads): front-and-center "active now" panel with live elapsed timers bvandeusen 2026-05-28 19:36:49 -04:00
  • c87e8e0932 fix(ui): render absolute timestamps in the viewer's local timezone bvandeusen 2026-05-28 19:36:42 -04:00
  • 8c3900b998 feat(showcase): dramatic 3D cascade entry — tiles tip back then settle into place bvandeusen 2026-05-28 19:01:04 -04:00
  • 972d9014ce feat(showcase): IR-parity hover animation on masonry thumbnails bvandeusen 2026-05-28 18:58:05 -04:00
  • 75b6b8056e feat(posts): plain bold titles; reserve View-original to the post card; provenance links to the posts feed bvandeusen 2026-05-28 18:18:34 -04:00
  • 42ddac9996 fix(subscriptions): fixed-height hub so only the tab content scrolls bvandeusen 2026-05-28 18:13:19 -04:00
  • 384d8d5e50 Merge pull request 'Dashboard insights + project-wide DRY pass' (#32) from dev into main bvandeusen 2026-05-28 15:38:26 -04:00
  • 1322056b22 refactor(dry-F5): useTabQuery composable for ?tab= query-param routing bvandeusen 2026-05-28 15:20:30 -04:00
  • 32bdde049f refactor(dry-B3): extract _get_or_create race-safe find-or-create in Importer bvandeusen 2026-05-28 15:02:55 -04:00
  • 9d18dacbe8 fix(lint): UP037 — drop quotes from ImportSettings.load return annotations (py3.14 deferred annotations) bvandeusen 2026-05-28 14:08:24 -04:00
  • 171c486939 refactor(dry-B2): ImportSettings.load()/load_sync() classmethods for the singleton row bvandeusen 2026-05-28 14:03:26 -04:00
  • 21c1b0a81c refactor(dry-B4): extract shared async_session_factory for Celery tasks bvandeusen 2026-05-28 13:15:04 -04:00
  • 597c6d48d3 refactor(dry-B1): consolidate duplicated _bad error helper into api/_responses.py bvandeusen 2026-05-28 13:10:04 -04:00
  • a37dad33c7 refactor(dry-F1): shared useAsyncAction lifecycle helper for stores bvandeusen 2026-05-28 12:53:57 -04:00
  • cabd73287a fix(lint): S1 ruff fallout — collapse double blank after import block (I001) + strip W293 in test_suggestions_bulk bvandeusen 2026-05-28 12:43:08 -04:00
  • def967a1a8 refactor(dry-S1): hoist app/client test fixtures into conftest bvandeusen 2026-05-28 11:33:05 -04:00
  • eebc8e2413 refactor(dry-F2): centralize shared UI primitives (relative-time, toast, download-status) bvandeusen 2026-05-28 11:20:07 -04:00
  • 2358cedf3e feat(dashboards): scheduler health strip, failing-source rollup, 24h activity sparkline, credential staleness nudge bvandeusen 2026-05-28 08:30:14 -04:00
  • 215a8993a1 fix(lint): noqa ASYNC109 on gallery_dl.verify timeout (subprocess.run deadline, not coroutine) bvandeusen 2026-05-28 08:18:33 -04:00
  • a459d21a65 feat(dashboards): 1600px max-width, richer Downloads filters, needs-attention + sticky headers bvandeusen 2026-05-28 08:10:04 -04:00
  • 73520b7cc3 feat(downloads): copy buttons in the download detail modal bvandeusen 2026-05-28 07:54:40 -04:00
  • 56970fb66d feat(credentials+downloads): real credential Verify button + live download-activity polling bvandeusen 2026-05-28 07:52:20 -04:00
  • bf8eb4468f feat(tags): legacy-tag purge also catches source:* general tags bvandeusen 2026-05-28 01:20:41 -04:00
  • e1fc65bd1b feat(provenance+tags): collapse provenance descriptions; purge retired-kind tags bvandeusen 2026-05-28 01:12:20 -04:00
  • 104cac5dca fix(ui): tooltip readability — dark bg + parchment text (was light-on-light) bvandeusen 2026-05-28 00:56:47 -04:00
  • 319e8c1d18 Merge pull request 'v26.05.28.0: downloads dashboard + task-resilience overhaul (timeouts, archive split, 3-layer poison-pill defense)' (#31) from dev into main v26.05.28.0 bvandeusen 2026-05-28 00:45:00 -04:00
  • dcfe55d731 feat(import-resilience L2): one-shot re-download for corrupt downloaded files bvandeusen 2026-05-28 00:08:03 -04:00
  • e3cdd0f92b feat(import-resilience L3): subprocess-isolated probes for video + archive bvandeusen 2026-05-28 00:01:32 -04:00
  • e77afe8295 feat(import-resilience L1): poison-pill circuit breaker — cap stuck-task re-queues bvandeusen 2026-05-27 23:54:35 -04:00
  • 57a22d6098 fix(tests): repair test_maintenance — skips_fresh_running tail was orphaned at module scope by the inserted ml/archive sweep tests (F841/F821) bvandeusen 2026-05-27 23:06:00 -04:00
  • a85880f965 fix(import): split archive imports into their own task + budget; archive-aware recovery sweeps bvandeusen 2026-05-27 22:45:11 -04:00
  • 407de18ff6 fix(ml): video branch needs longer time limits; recovery sweep is now per-queue bvandeusen 2026-05-27 22:23:35 -04:00
  • b1b129ce9f feat(downloads-tab): A+B dashboard improvements — row restyle + date-grouped sections with failed-pinned bvandeusen 2026-05-27 22:18:02 -04:00
  • 9075d8eadd Merge pull request 'v26.05.27.2: subscribestar + HF cookie quirks, platforms package refactor, showcase IR-parity, secure-context audit' (#30) from dev into main v26.05.27.2 ext-1.0.5 bvandeusen 2026-05-27 21:34:02 -04:00
  • df6d89cb59 fix(secure-context): full audit — DestructiveConfirmModal.expectedTokenOverride + bulk-delete + min-dim use backend-computed tokens bvandeusen 2026-05-27 21:17:40 -04:00
  • 12be188ada feat(showcase): IR-parity R-key shuffle + stagger entry animation; fix(cleanup): min-dim Delete swallowed crypto.subtle TypeError on plain HTTP bvandeusen 2026-05-27 20:59:58 -04:00
  • 6d7116c090 fix(platforms): ruff I001 in base.py — one blank line between imports and module-level constant (was two) bvandeusen 2026-05-27 20:37:06 -04:00
  • b447c42853 fix(platforms): ruff I001 — drop unused __future__ import; switch __init__ to per-module imports for clean isort ordering bvandeusen 2026-05-27 19:52:50 -04:00
  • abafc3265e refactor(platforms): promote services/platforms.py → services/platforms/ package with per-platform quirk colocation bvandeusen 2026-05-27 19:46:05 -04:00
  • 2394e47370 fix(hentaifoundry): inject host-only PHPSESSID/CSRF duplicates + extension preserves browser hostOnly bvandeusen 2026-05-27 19:12:51 -04:00
  • 8243740a04 fix(subscribestar): inject 18_plus_agreement_generic age cookie to bypass server gate bvandeusen 2026-05-27 18:18:04 -04:00
  • 88e53e5b86 Merge pull request 'v26.05.27.1: subscriptions hub + post-card merge + sidecar audit' (#29) from dev into main v26.05.27.1 bvandeusen 2026-05-27 17:12:48 -04:00
  • aa28bddeab fix(alembic 0025): qualify ambiguous post.id / post.source_id in fragment-group SELECT (post JOIN source — both have id) bvandeusen 2026-05-27 15:45:42 -04:00
  • b7b313cc05 fix(alembic 0025): include HF + Discord post_url backfill (no longer 'deferred to deep-scan') bvandeusen 2026-05-27 15:38:18 -04:00
  • bd3f996582 fix(sidecar): correct external_post_id + post_url derivation for non-Patreon platforms bvandeusen 2026-05-27 15:35:25 -04:00
  • ae8c78ae09 fix(sidecar): synthesize post_title from content first-line when title is empty (subscribestar) bvandeusen 2026-05-27 14:44:09 -04:00
  • 4d2c464045 feat(post-card): absorb PostModal into PostCard with click-to-expand bvandeusen 2026-05-27 14:30:04 -04:00
  • b8ad17c68d fix(build): poll for ext-<version> release in tag-push build-web (race fix) bvandeusen 2026-05-27 13:25:58 -04:00
  • 1fd54897d8 fix(api): ruff UP017 — use datetime.UTC alias in /api/downloads/stats bvandeusen 2026-05-27 13:11:44 -04:00
  • 9322c984fd feat(subs-hub): collapse /credentials + /downloads into /subscriptions hub with three GS-style subtabs bvandeusen 2026-05-27 13:02:24 -04:00
  • 37e8b796a1 Merge pull request 'v26.05.27.0: PostCard redesign + IR-style tag suffix + drop meta/rating + extension v1.0.4 CSP fix' (#28) from dev into main v26.05.27.0 ext-1.0.4 bvandeusen 2026-05-27 11:31:18 -04:00
  • 8675f105ad fix(tests): test_api_tags prefix tests use character: not artist: (KNOWN_KINDS dropped artist) bvandeusen 2026-05-27 11:09:04 -04:00
  • 74dac6b960 fix(extension+migration): MV3 CSP opt-out from upgrade-insecure-requests (v1.0.4) + alembic 0023 drops the ck_tag_fandom_requires_character check before the type swap bvandeusen 2026-05-26 21:57:38 -04:00
  • 9e19c081b0 fix(test): pin tag_kind enum test to the post-0023 set (meta + rating removed) bvandeusen 2026-05-26 21:23:12 -04:00
  • 3838f04c16 feat(tag-kinds): drop meta + rating entirely — alembic 0023 deletes existing meta/rating tags (CASCADE clears related image_tag / alias / allowlist / suggestion_rejection / reference_embedding / series_page rows) then recreates the tag_kind ENUM without those values. Python TagKind enum trimmed; KIND_OPTIONS + KIND_COLOR + KIND_ICONS maps + TagsView KINDS array all updated. Operator confirmed they have no use for the data. bvandeusen 2026-05-26 21:07:31 -04:00
  • 42b1340324 fix(tag-prefix): drop artist/meta/rating from KNOWN_KINDS — artist tags retired in FC-2d-vii-c (provenance is its own axis), meta/rating retired by operator 2026-05-26. User-typeable prefixes now just character/fandom/series. Frontend placeholder + icon map + client-side mirror updated; new test confirms retired prefixes parse as literal text. bvandeusen 2026-05-26 21:00:12 -04:00
  • 3b1e2f1ceb feat(tag-input): IR-style kind:name suffix — drop the kind dropdown from TagAutocomplete; client-side parser mirrors backend's parse_kind_prefix (KNOWN_KINDS = artist/character/fandom/series/meta/rating); autocomplete searches across all kinds and shows kind chip in results; Create label uses parsed kind; character flow still goes through FandomPicker bvandeusen 2026-05-26 20:54:11 -04:00
  • 8cdf0af0e1 feat(tags-api): IR-style kind:name parsing at POST /api/tags — when caller doesn't supply explicit kind, parse_kind_prefix runs on the name (artist:Eric → kind=artist, name='Eric'); explicit kind always wins for backward-compat; falls back to general when no recognized prefix is present. Updates the old "missing required" test that assumed kind was mandatory. bvandeusen 2026-05-26 20:53:27 -04:00
  • ccee344099 feat(tag-prefix): parse_kind_prefix util — IR-style \kind:name\ parser at the input boundary; KNOWN_KINDS = artist/character/fandom/series/meta/rating (excludes default \general\ and system-managed archive/post) bvandeusen 2026-05-26 20:51:49 -04:00
  • 0316f92e8b feat(artist-posts-tab): bump max-width 900 → 1600 so the new wide-layout PostCard has room and the artist Posts feed doesn't leave most of an ultra-wide screen empty bvandeusen 2026-05-26 20:51:21 -04:00
  • 6df74683b3 feat(post-card): responsive redesign — container-query split (stack <800px / side-by-side ≥800px), hero + thumb rail, +N overflow chip, line-clamp body (3 narrow / 5 wide), title/desc fallbacks for sparse data, click→postModal.open bvandeusen 2026-05-26 20:51:10 -04:00
  • 243e536225 feat(app): mount PostModal at app root next to ImageViewer — single instance driven by usePostModalStore so PostCard can open from anywhere bvandeusen 2026-05-26 20:50:34 -04:00
  • 2f16699971 feat(post-modal): PostModal — full Patreon-style v-dialog (header + image grid + sanitized body + attachments); reads from usePostModalStore bvandeusen 2026-05-26 20:49:59 -04:00
  • a5cb684d34 feat(post-modal): PostImageGrid — fixed-cell grid (auto-fill 220px+, 4:3 aspect-cover) inside PostModal; click opens ImageViewer scoped to the post's images via modalStore.open(id, { postImageIds }) bvandeusen 2026-05-26 20:49:20 -04:00
  • 965a953b2e feat(post-card): PostEmptyThumbs — dashed-border placeholder shown in PostCard's hero slot when post has zero linked images bvandeusen 2026-05-26 20:49:02 -04:00
  • 90c176b195 feat(postmodal-store): Pinia store driving the app-level PostModal — open(post) fetches full detail via posts store; close() clears bvandeusen 2026-05-26 20:48:49 -04:00
  • b8d89b9f2a feat(modal-store): post-scoped cycle — open(id, { postImageIds }) pins prev/next to the array; canPrev/canNext + goPrev/goNext check the array index instead of current.value.neighbors when set. Gallery-context callers unchanged (default args clear scope) bvandeusen 2026-05-26 20:48:30 -04:00
  • 07344e0843 feat(util): htmlSanitize — whitelist-based DOM scrubber for PostModal's description v-html (Patreon ships HTML; sanitize before render) bvandeusen 2026-05-26 20:47:36 -04:00
  • 42c33e44f9 feat(post-api): get_post returns uncapped thumbnails — PostModal masonry needs full image list; feed query unchanged (still capped at 6 for previews). _thumbnails_for gains a limit kwarg; get_post passes limit=None. bvandeusen 2026-05-26 20:47:18 -04:00
  • 4e82208926 Merge pull request 'v26.05.26.5 — extension CORS unblock + UI gap closes + CI workflow cleanup' (#27) from dev into main v26.05.26.5 bvandeusen 2026-05-26 20:15:07 -04:00
  • 85b640f32e fix(views): close the 24-32px gap below TopNav across all views — every v-container had py-6 (or py-8 on PlaceholderView) which pushed the first content item well below where the TopNav's fade-to-transparent gradient bottoms out. Switch to pt-2 pb-6 (8px top, 24px bottom) so content sits comfortably right below the nav, matches the ArtistHeader's 'continuous with TopNav' feel. PlaceholderView uses pt-3 pb-8 keeping its larger bottom padding. bvandeusen 2026-05-26 19:47:23 -04:00
  • c7001f4aed fix(extension): CORS preflight for moz-extension:// + chrome-extension:// origins — operator-flagged 2026-05-26 that the extension's Test connection returned NetworkError because /api/credentials POSTs with X-Extension-Key trigger a browser preflight OPTIONS that hit a 405 (no OPTIONS method registered) with no Access-Control-Allow-* headers. Adds two app-level hooks: before_request short-circuits OPTIONS from extension origins with 204, after_request stamps the necessary ACL headers on responses to extension-origin requests. Whitelist is intentionally narrow (extension schemes only) so normal browser usage doesn't get permissive CORS. Five integration tests pin the contract. bvandeusen 2026-05-26 19:43:31 -04:00
  • f827612930 fix(artist-header): close gap below TopNav (top:64px → 48px to match TopNav's actual ~48px height) + center the tab strip via 1fr|auto|1fr layout with a right-side spacer cell bvandeusen 2026-05-26 18:36:19 -04:00
  • 3f0153cba5 ci(workflows): dedupe + versioned image tags bvandeusen 2026-05-26 18:26:56 -04:00
  • 52fff00353 Merge pull request 'v26.05.26.4 — hotfix: migration 0022 pre-DELETE colliding ImageProvenance before UPDATE' (#26) from dev into main v26.05.26.4 bvandeusen 2026-05-26 18:06:20 -04:00
  • f3e8f30a8f fix(migration-0022): pre-DELETE colliding image_provenance rows before the UPDATE post_id — same row-by-row UNIQUE pattern as the post-collision case, just one level deeper. When image X has provenance under both keep and drop, UPDATE drop→keep would fire uq_image_provenance_image_post on the row that'd collide with the existing (X, keep). Pre-delete those rows (their info is already represented by the keep-side provenance) before the UPDATE moves the rest. bvandeusen 2026-05-26 18:05:49 -04:00
  • eee107766e fix(migration-0022): rename unused _epid loop var (ruff B007) bvandeusen 2026-05-26 18:03:11 -04:00
  • c14338cbce Merge pull request 'v26.05.26.3 — hotfix: migration 0022 pre-merge across ENTIRE (canonical+others) group' (#25) from dev into main v26.05.26.3 bvandeusen 2026-05-26 17:52:59 -04:00
  • 7a64730bd2 fix(migration-0022): pre-merge ALL duplicate-external_post_id Posts across the (canonical+others) group, not just canonical-vs-others — operator's v26.05.26.2 deploy still tripped uq_post_source_external_id because two non-canonical Sources both had Posts with epid=6166997. Bulk UPDATE moved the first cleanly then collided on the second. New pre-merge groups all Posts in the (artist, platform) by external_post_id; for any group with count>1, picks the keep (prefer one under canonical; else lowest id) and merges the rest before the bulk reparent. bvandeusen 2026-05-26 17:52:29 -04:00
  • 1803a09306 ci(workflow): remove the 4 Cache pip wheels steps entirely — act_runner's cache backend has been broken for 11+ days and the cached path (~/.cache/pip) wasn't even the primary install tool's cache anyway (uv uses ~/.cache/uv). Net cost ~30s/job of wheel downloads. Long-term: mount ~/.cache/uv as a docker volume at the runner level (skips actions/cache entirely) or fix the runner-side cache backend. bvandeusen 2026-05-26 16:54:05 -04:00
  • 8c36dd28b0 Merge pull request 'v26.05.26.2 — hotfix: alembic 0022 Post-collision pre-merge + ci.yml cache continue-on-error' (#24) from dev into main v26.05.26.2 bvandeusen 2026-05-26 16:50:43 -04:00
  • 0f7cd3cb76 fix(migration-0022): pre-merge colliding Posts before the bulk reparent — Postgres fires uq_post_source_external_id row-by-row during UPDATE, so the post-reparent merge-collisions step never ran (operator's v26.05.26.1 deploy hit it: 'duplicate key (source_id, external_post_id)=(42, 6166997)'). Detect (keep, drop) Post pairs whose external_post_id already exists under canonical, merge the drop into keep, then bulk-reparent the rest cleanly. bvandeusen 2026-05-26 16:48:49 -04:00
  • 7b0dd4182c ci(workflow): continue-on-error on Cache pip wheels — act_runner's cache backend has been broken since 2026-05-15 and now hard-fails ('Cannot find module .../dist/restore/index.js') instead of warning. Install step handles cold caches natively; ~30s wheel-download cost per job until the runner-side cache backend is fixed. bvandeusen 2026-05-26 16:35:26 -04:00
  • 88cfb3dd02 Merge pull request 'v26.05.26.1 — thumb backfill, modal redesign, recovery sweep race-safety, artist view redesign, extension fixes' (#23) from dev into main v26.05.26.1 bvandeusen 2026-05-26 16:32:00 -04:00
  • fb41b90110 fix(extension): _find_or_create_artist + _find_or_create_source race-safe via savepoint + IntegrityError recovery — same pattern as importer's helpers. Two concurrent quick-add-source calls on the same artist/url would have 500'd on uq_artist_slug / uq_source_artist_platform_url; now the second one rolls the savepoint back and returns the existing row. bvandeusen 2026-05-26 16:27:51 -04:00
  • 7d84990f6d feat(artist-view): ArtistView rewrite — sticky frosted ArtistHeader (name + stats + tabs) replaces the in-body h1; three lazy tabs (Posts default, Gallery fallback, Management); ?tab= URL state; cross-artist store reset; document.title set on slug change bvandeusen 2026-05-26 16:01:14 -04:00
  • ca55d92c68 feat(artist-view): ArtistManagementTab — Overview chips (Subscription badge + subscription count) + Frequent tags + Activity sparkline + Subscriptions table + Danger zone. 'View posts' chip and 'Credential health · FC-3b' placeholder chip dropped; 'Sources' section renamed to 'Subscriptions' bvandeusen 2026-05-26 16:00:47 -04:00
  • cce014be3a feat(artist-view): ArtistGalleryTab — MasonryGrid wired to the artist store's existing loadMoreImages; modal-open preserves ?tab=. No global gallery-store coupling (avoids cross-pollution into /gallery) bvandeusen 2026-05-26 16:00:14 -04:00
  • c07effb593 feat(artist-view): ArtistPostsTab — PostCard infinite-scroll list, artist_id pinned, no filter bar; mirrors PostsView mechanics bvandeusen 2026-05-26 16:00:02 -04:00