v26.05.27.1: subscriptions hub + post-card merge + sidecar audit #29

Merged
bvandeusen merged 0 commits from dev into main 2026-05-27 17:12:48 -04:00
bvandeusen commented 2026-05-27 16:58:06 -04:00 (Migrated from git.fabledsword.com)

Summary

Eight commits, three themes:

1. Subscriptions hub restructure (9322c98). Collapses /credentials and /downloads into a single /subscriptions parent with three internal subtabs (Subscriptions default | Downloads | Settings) — tab state via ?tab= query param, mirroring ArtistView's pattern. Adopts GS visual language across all three: color-coded PlatformChip, GS-style Downloads dashboard (stat chips + popover filter + maintenance menu + retry-per-row), GS-style credentials card grid in Settings. Pulls download + schedule settings out of Settings → Import into the new Settings subtab. New backend endpoint GET /api/downloads/stats?window_hours= (pinned by two integration tests). /credentials and /downloads keep working as bookmark-safety redirects into the new ?tab= form.

2. PostCard absorbs PostModal (4d2c464). The wider PostCard layout had enough real estate to be the canonical post surface, so the modal is collapsed in. Compact state unchanged. Click-to-expand inline: full title, mosaic of ALL post images via PostImageGrid (lazy-loaded uncapped thumbnails via getPostFull), full sanitized-HTML description, attachments as downloadable pills. Mosaic image clicks still open ImageViewer scoped to the post. Per-card local state — usePostModalStore deleted.

3. Sidecar audit fixes (ae8c78a, bd3f996, b7b313c, aa28bdd). Audit of one sample sidecar per platform on the operator's /mnt/Data/Patreon/ archive surfaced three parser bugs that had been silently corrupting non-Patreon Posts since FC-3 shipped:

  • SubscribeStar id vs post_id: gallery-dl puts the per-attachment id in id and the actual post id in post_id. Reorder the external_post_id chain to (post_id, id, index, message_id) so SubscribeStar's multi-image posts no longer fragment into N rows.
  • SubscribeStar/Pixiv/HF/Discord post_url was the file CDN URL. New _derive_post_url(platform, data) synthesizes proper permalinks per platform; Patreon's bare url (a real permalink) stays as-is.
  • Discord message body field not captured — added to the description fallback chain.
  • SubscribeStar title always empty (separate fix already shipped in ae8c78a for the parser + alembic 0024 backfill).

12 new sidecar-util tests pin per-platform parsing behavior.

Migrations

Two destructive migrations land in this release:

  • alembic 0024_backfill_post_title_from_description — backfills the synthesized title for existing Post rows where post_title IS NULL OR '' and a description is present. Idempotent.
  • alembic 0025_fix_subscribestar_post_ids — walks each SubscribeStar / HF / Discord Post, reads its sidecar from disk (ImageRecord.path → sidecar JSON), overwrites external_post_id (subscribestar only) + post_url (all three). After updates, merges SubscribeStar Post groups under one source that now share an external_post_id (same ImageProvenance pre-delete + repoint dance as alembic 0022). Pure-SQL Pixiv post_url backfill in the same migration. Idempotent. Migration logs per-platform counts (read N sidecars, updated N Posts, N had no resolvable sidecar) to stdout.

After this release, the only Posts still pointing at file URLs are those whose ImageRecord.path doesn't resolve on disk at migration time (orphan filesystem state) — a future deep-scan would catch the rest.

Infrastructure

b8ad17c build.yml race fix. Cutting a release fires both the push-to-main and push-to-tag workflows in parallel. main-push's sign-extension takes 1–5 min for AMO; tag-push's build-web's "Download signed XPI" raced past it and 404'd on the missing ext-<version> release every time (operator hit this on v26.05.27.0). Wrap the release lookup in a 20-iteration sleep+retry loop (30s × 20 = 10 min upper bound) so tag-push naturally waits for main-push's sign step.

Test plan

  • CI green (Forgejo Actions)
  • Deploy: :latest pulled, services force-recreated, alembic 0024 + 0025 applied cleanly
  • Confirm 0025 stdout shows non-zero read N sidecars per platform (subscribestar/HF/discord) on the operator's database
  • /subscriptions lands on Subscriptions subtab by default; ?tab=downloads and ?tab=settings work; legacy /credentials and /downloads redirect into the hub
  • PostCard click expands inline with full text + image mosaic + attachments; chevron collapses; mosaic image click opens ImageViewer scoped to post
  • SubscribeStar posts in PostCard show meaningful titles (derived from first content line), post_url resolves to subscribestar.com/posts/<id> not a CDN URL
  • Multi-image SubscribeStar posts are now single Post rows (verify via DB: SELECT external_post_id, COUNT(*) FROM post JOIN source ON ... WHERE platform='subscribestar' GROUP BY 1 HAVING COUNT(*) > 1 → 0 rows)
  • tag-push build no longer races (this release will exercise it for real)
## Summary Eight commits, three themes: **1. Subscriptions hub restructure (`9322c98`).** Collapses `/credentials` and `/downloads` into a single `/subscriptions` parent with three internal subtabs (Subscriptions default | Downloads | Settings) — tab state via `?tab=` query param, mirroring ArtistView's pattern. Adopts GS visual language across all three: color-coded `PlatformChip`, GS-style Downloads dashboard (stat chips + popover filter + maintenance menu + retry-per-row), GS-style credentials card grid in Settings. Pulls download + schedule settings out of `Settings → Import` into the new Settings subtab. New backend endpoint `GET /api/downloads/stats?window_hours=` (pinned by two integration tests). `/credentials` and `/downloads` keep working as bookmark-safety redirects into the new `?tab=` form. **2. PostCard absorbs PostModal (`4d2c464`).** The wider PostCard layout had enough real estate to be the canonical post surface, so the modal is collapsed in. Compact state unchanged. Click-to-expand inline: full title, mosaic of ALL post images via PostImageGrid (lazy-loaded uncapped thumbnails via getPostFull), full sanitized-HTML description, attachments as downloadable pills. Mosaic image clicks still open ImageViewer scoped to the post. Per-card local state — `usePostModalStore` deleted. **3. Sidecar audit fixes (`ae8c78a`, `bd3f996`, `b7b313c`, `aa28bdd`).** Audit of one sample sidecar per platform on the operator's `/mnt/Data/Patreon/` archive surfaced three parser bugs that had been silently corrupting non-Patreon Posts since FC-3 shipped: - SubscribeStar `id` vs `post_id`: gallery-dl puts the per-attachment id in `id` and the actual post id in `post_id`. Reorder the external_post_id chain to `(post_id, id, index, message_id)` so SubscribeStar's multi-image posts no longer fragment into N rows. - SubscribeStar/Pixiv/HF/Discord `post_url` was the file CDN URL. New `_derive_post_url(platform, data)` synthesizes proper permalinks per platform; Patreon's bare `url` (a real permalink) stays as-is. - Discord `message` body field not captured — added to the description fallback chain. - SubscribeStar `title` always empty (separate fix already shipped in `ae8c78a` for the parser + alembic 0024 backfill). 12 new sidecar-util tests pin per-platform parsing behavior. ## Migrations Two destructive migrations land in this release: - **`alembic 0024_backfill_post_title_from_description`** — backfills the synthesized title for existing Post rows where `post_title IS NULL OR ''` and a description is present. Idempotent. - **`alembic 0025_fix_subscribestar_post_ids`** — walks each SubscribeStar / HF / Discord Post, reads its sidecar from disk (`ImageRecord.path` → sidecar JSON), overwrites `external_post_id` (subscribestar only) + `post_url` (all three). After updates, merges SubscribeStar Post groups under one source that now share an external_post_id (same ImageProvenance pre-delete + repoint dance as alembic 0022). Pure-SQL Pixiv `post_url` backfill in the same migration. Idempotent. Migration logs per-platform counts (`read N sidecars, updated N Posts, N had no resolvable sidecar`) to stdout. After this release, the only Posts still pointing at file URLs are those whose ImageRecord.path doesn't resolve on disk at migration time (orphan filesystem state) — a future deep-scan would catch the rest. ## Infrastructure **`b8ad17c` build.yml race fix.** Cutting a release fires both the push-to-main and push-to-tag workflows in parallel. main-push's sign-extension takes 1–5 min for AMO; tag-push's build-web's "Download signed XPI" raced past it and 404'd on the missing `ext-<version>` release every time (operator hit this on v26.05.27.0). Wrap the release lookup in a 20-iteration sleep+retry loop (30s × 20 = 10 min upper bound) so tag-push naturally waits for main-push's sign step. ## Test plan - [ ] CI green (Forgejo Actions) - [ ] Deploy: `:latest` pulled, services force-recreated, alembic 0024 + 0025 applied cleanly - [ ] Confirm 0025 stdout shows non-zero `read N sidecars` per platform (subscribestar/HF/discord) on the operator's database - [ ] `/subscriptions` lands on Subscriptions subtab by default; `?tab=downloads` and `?tab=settings` work; legacy `/credentials` and `/downloads` redirect into the hub - [ ] PostCard click expands inline with full text + image mosaic + attachments; chevron collapses; mosaic image click opens ImageViewer scoped to post - [ ] SubscribeStar posts in PostCard show meaningful titles (derived from first content line), `post_url` resolves to `subscribestar.com/posts/<id>` not a CDN URL - [ ] Multi-image SubscribeStar posts are now single Post rows (verify via DB: `SELECT external_post_id, COUNT(*) FROM post JOIN source ON ... WHERE platform='subscribestar' GROUP BY 1 HAVING COUNT(*) > 1` → 0 rows) - [ ] tag-push build no longer races (this release will exercise it for real)
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/FabledCurator#29