Commit Graph
260 Commits
Author SHA1 Message Date
adminandClaude Opus 4.8 abdfa437d9 feat(worker): RAR vint/signature/block-extent parsers
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 11:39:19 +02:00
admin 49f14bcb0d feat(worker): dispatch 7z ranged listing + size-capped full-download fallback 2026-07-27 11:29:08 +02:00
adminandClaude Opus 4.8 d4a1cfec99 feat(worker): ranged 7z listing orchestrator + RangeReader
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 11:22:08 +02:00
admin ecedc0fec4 feat(worker): 7z signature-header parser 2026-07-27 11:17:58 +02:00
admin 1b1f5b7972 feat(worker): sparse-file reconstruction helper for ranged archive listing 2026-07-27 11:14:17 +02:00
adminandClaude Opus 4.8 e822ea3e76 docs: implementation plan for ranged RAR/7z inner-file listing
8 TDD tasks: sparse reconstruction, 7z end-header read, RAR block-walk
(incl. multipart), size-capped full-download fallback, format-aware
dispatch. 7z ships first behind the fallback as the productive spike.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 07:16:20 +02:00
adminandClaude Opus 4.8 9d16156161 docs: design for ranged inner-file listing (RAR & 7z)
Cheap listing without full download for RAR/7z placeholders: harvest header
regions via ranged reads, sparse-reconstruct, list with native 7z/unrar CLIs.
Full-download fallback (size-capped) for stragglers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 06:41:34 +02:00
adminandClaude Opus 4.8 2e7e6cca9b Backup: switch NAS transport to SMB/CIFS, fix crond/OOM/live-tar defects
Wire the backup service against the Synology share over SMB/CIFS (the NAS
authenticates with a user/password; NFS is IP-allowlist only). Also fixes
three defects found bringing the service up live:

- entrypoint crash-loop: dcron's crond fails "setpgid: Operation not
  permitted" in this runtime -> use busybox crond; make repo-init idempotent
  (check via `restic cat config`, tolerate init-on-existing) so a transient
  CIFS/lock hiccup can't kill PID 1.
- OOM: pg_dump of a ~276MB DB + tar + restic exceeded the 256M cap -> 1G.
- live tar abort: GNU tar exits 1 when TDLib files change mid-read (worker is
  live); per design this is best-effort, so tolerate exit 1, fatal only >=2.

Kuma push is now optional (empty URL disables alerting) since it's deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 11:36:19 +02:00
adminandClaude Opus 4.8 ceae4f384b Fix provenance-backfill multipart offsets, incomplete-fingerprint fallback, and add name-size audit trail
Multipart ZIP fingerprint reads now use per-part sizes instead of the
whole-archive total, so the tail download offset stays within the last
part's bounds on both the scanned side and the destination-copy side
(scannedFileId replaced with an ordered scannedParts list). A fingerprint
comparison is now only treated as a real mismatch when both sides have
complete CRCs and differ; incomplete comparisons (e.g. empty files) fall
back to name+size confidence instead of silently refusing to backfill.
Name+size-confidence backfills now also create an INFO
INTEGRITY_AUDIT systemNotification for later review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:46:45 +02:00
adminandClaude Opus 4.8 7595543386 feat(worker): notify on ambiguous provenance candidates instead of guessing
When multiple placeholder packages share the same name+size, try to
disambiguate via ZIP fingerprint; if that can't uniquely resolve a
single match, emit a SystemNotification and skip the backfill rather
than attributing provenance to the wrong package.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:28:34 +02:00
adminandClaude Opus 4.8 09ee9da9cc feat(worker): fingerprint listing-less ZIP candidates via destination copy
Rebuild-created placeholder candidates have no PackageFile CRCs, so
name-side fingerprinting can't confirm them. When the stored candidate
fingerprint is incomplete, read the candidate's own copy from its
destination message and fingerprint against that instead of falling
straight to name+size confidence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:27:07 +02:00
adminandClaude Opus 4.8 7ddf13053f feat(worker): opportunistic provenance backfill during scan
Wire tryProvenanceBackfill into processOneArchiveSet: before downloading
a scanned ZIP/RAR/7Z, check whether it's the true origin of a
placeholder-provenance package in the destination channel and backfill
in place, skipping the download. Add the zipsBackfilled counter through
PipelineContext, updateRunActivity, and completeIngestionRun.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:23:53 +02:00
adminandClaude Opus 4.8 4a7b9e2a09 feat(db): IngestionRun.zipsBackfilled counter
Additive migration (applied on deploy via prisma migrate deploy). Counts
packages whose provenance was backfilled during an ingestion run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:20:07 +02:00
adminandClaude Opus 4.8 9a06130c5b feat(worker): provenance-backfill orchestrator
Implements tryProvenanceBackfill() per Task 6 of the provenance-backfill
plan: looks up a placeholder candidate by fileName+fileSize, confirms ZIP
candidates via a ranged central-directory CRC32 fingerprint, and falls
back to name+size confidence for RAR/7z/failed listings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 13:23:15 +02:00
adminandClaude Opus 4.8 a7aa4ce285 feat(worker): DB helpers for provenance backfill
Adds findPlaceholderCandidate, getPackageFileCrcs, and
backfillProvenance to worker/src/db/queries.ts (Task 5). Candidate
predicate matches placeholder packages by source==dest or the
sourceMessageId==0 rebuild sentinel; backfillProvenance re-checks
placeholder status inside the transaction before overwriting fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 13:12:41 +02:00
adminandClaude Opus 4.8 38072d250f feat(worker): ranged TDLib file download (downloadFileRange)
Implements Task 4 Step 2 of the provenance-backfill plan. The live
spike (Step 1) and manual verification (Step 3) were not run in this
environment because a second TDLib client would corrupt the running
worker's authenticated session; the absolute-offset assumption is
noted as pending live verification on deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 13:12:37 +02:00
adminandClaude Opus 4.8 0bce1168a9 docs: correct provenance-backfill candidate predicate for rebuild records
Rebuild records use sourceMessageId=0 + synthetic 'rebuild:' contentHash and an
arbitrary fallback sourceChannelId, so the original sourceChannelId==destChannelId
candidate definition missed them. Predicate is now
(sourceChannelId==destChannelId OR sourceMessageId==0), verified against 59,893
live rebuilt records.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 13:05:34 +02:00
adminandClaude Opus 4.8 018b0f5d74 feat(worker): parse ZIP central directory from a tail buffer
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:20:16 +02:00
adminandClaude Opus 4.8 c2590fb66f feat(worker): CRC32 archive fingerprint compare
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:19:28 +02:00
adminandClaude Opus 4.8 8b443620c8 test(worker): add vitest harness
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:18:57 +02:00
adminandClaude Opus 4.8 80aa2b0ee0 docs: provenance-backfill spec and implementation plan
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:05:26 +02:00
adminandClaude Opus 4.8 f0e0e79d34 fix(auth): survive a stale session whose user was deleted
A JWT session pointing at a user no longer in the DB (e.g. after a DB reset)
made getUserSettings create settings for a non-existent user -> FK violation
(P2003) -> Server Component render crash. getUserSettings now returns defaults
on P2003; the (app) layout detects the missing user and redirects to a new
server-side /logout route that clears the cookie, avoiding the middleware
redirect loop that otherwise blocks reaching /login.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:05:26 +02:00
adminandClaude Opus 4.8 21bd46010f feat(stls): flat package list, drop heuristic auto-grouping
Render the STL view as a flat per-package list (listDisplayItems no longer
collapses packages into group rows) and hide the Ungrouped tab, now that the
creator filter organizes the list. Remove the worker's heuristic auto-grouping
passes (rule/time/pattern/creator/zip-path/reply-chain/caption); album grouping
is kept. Existing groups and manual grouping actions are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:05:18 +02:00
admin 2252ac01f5 Add build-backup CI step, include it in deploy dependencies 2026-07-23 01:17:35 +02:00
adminandClaude Sonnet 5 63df348028 Fix db service network alias for backup.sh pg_dump connection
The backup.sh script hardcodes 'pg_dump -h dragonsstash-db' (matching
production), but the db service lacked a network alias for that hostname.
Added network alias to the backend network so the backup service can
successfully connect using the hardcoded hostname.

Verified: both 'db' and 'dragonsstash-db' resolve from the backend network.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 01:15:20 +02:00
adminandClaude Sonnet 5 8bbf51f056 Add backup service and nas_backups volume to docker-compose.yml
Wires the backup service (from Tasks 1-2) into the production compose
configuration, adds NFS-backed nas_backups volume, and documents the four
required env vars (NAS_HOST, NAS_EXPORT_PATH, RESTIC_PASSWORD, KUMA_PUSH_URL, TZ)
in .env.example.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 01:09:35 +02:00
adminandClaude Sonnet 5 5873d148c1 Fix backup.sh: always clean up temp dump/tar files via EXIT trap
Previously the dump/tar cleanup only ran after restic forget succeeded,
so a plaintext Postgres dump could be left behind in /tmp if tar or
restic failed partway through. Add an EXIT trap that unconditionally
removes both temp files on any exit path, and drop the now-redundant
explicit rm -f from the success path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 01:06:22 +02:00
adminandClaude Sonnet 5 90be365c7f Implement backup.sh: pg_dump + tdlib tar + restic backup/forget + Kuma reporting
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 00:58:29 +02:00
admin 7e21a41615 Add backup service image (Dockerfile, entrypoint, crontab) 2026-07-23 00:53:34 +02:00
admin f3d62c68fb Add implementation plan for NAS-backed Postgres + TDLib backups
Six tasks: backup image, backup.sh, repo compose wiring, CI build
step, production compose wiring (gated on NAS/Kuma details from the
user), deploy + restore-drill verification.
2026-07-23 00:47:47 +02:00
admin 412e3066bc Add design spec for NAS-backed Postgres + TDLib backups
Restic-based backup container, encrypted daily backups to a Synology
NFS share, 14-day retention, Uptime Kuma alerting.
2026-07-23 00:41:06 +02:00
adminandClaude Opus 4.8 6178ff3b08 docs: add Task 3 (creator filter combobox) to plan
continuous-integration/drone/push Build is passing
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 09:42:37 +02:00
admin 57842c6d95 Merge feat/send-all-from-creator: send-all-from-creator button + searchable creator filter 2026-07-04 09:42:08 +02:00
admin b3c49c3794 feat(stls): add searchable creator filter combobox to toolbar 2026-07-04 09:36:51 +02:00
admin 20e60bc6af feat(stls): add 'send all from creator' toolbar button 2026-07-04 09:26:36 +02:00
admin 50e89719bb feat(stls): add sendAllFromCreatorAction server action 2026-07-04 09:20:36 +02:00
adminandClaude Opus 4.8 1cae855c26 docs: implementation plan for send-all-from-creator button
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 09:15:58 +02:00
adminandClaude Opus 4.8 b0baf72f0a docs: spec for send-all-from-creator button on STL page
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 09:14:33 +02:00
adminandClaude Opus 4.8 0cf5fcd3a7 fix(stls): stop loading preview blobs in list queries (OOM fix)
continuous-integration/drone/push Build is passing
The STLs list queries selected the full previewData JPEG bytes (avg
~700KB, up to 2MB, and every group member's preview) only to compute a
hasPreview boolean. Under concurrent page loads this piled blobs into
the Node heap, exceeded the 512MB container limit, crashed the process,
and surfaced as repeated connection errors while browsing.

Replace the byte-loading select with a fetchPreviewFlags() helper that
checks `previewData IS NOT NULL` in SQL (IDs only, no bytes). Applied to
listPackages, listDisplayItems, searchPackages, and listUngroupedPackages.

Verified: same concurrent load that drove memory to 508/512MB and forced
a restart now peaks at 156MB (30%) with zero failed requests and no restart.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 19:05:34 +02:00
adminandClaude Opus 4.8 3b7202a662 harden(telegram): reject non-positive topic id in disableActiveTopic
continuous-integration/drone/push Build is passing
BigInt("") / BigInt("0") don't throw; guard against them since the
action is exported and admin-callable independent of the UI button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:15:03 +02:00
adminandClaude Opus 4.8 23f8e91c50 feat(telegram): add "skip & disable topic" on the live worker panel
Track the forum topic currently being processed on IngestionRun
(currentTopicId + currentAccountChannelMapId; additive migration) and
expose it on the live status. processArchiveSets gains an optional
shouldStop callback polled before each archive set; the forum branch
passes a live isTopicFetchEnabled check, so disabling a topic mid-run
lets the in-flight file finish, then skips the rest of that topic.

A new disableActiveTopic server action sets the topic's fetchEnabled
false (upsert), and the worker status panel shows a "Skip & disable
this topic" button while a topic is being processed. Future runs skip
the topic via the existing live per-topic read.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:10:56 +02:00
admin c749d03376 Merge fix/topics-drawer-scroll-and-filter: topics drawer scroll + title filter
continuous-integration/drone/push Build is passing
2026-06-22 09:05:46 +02:00
adminandClaude Opus 4.8 d7771887a1 fix(worker): silence false-positive integrity-test notifications
The pre-upload integrity test is advisory (never blocks upload), but it
raised a WARNING SystemNotification whenever `7z t` failed — most often
because large 7z archives OOM-kill the test process (SIGKILL / exit 137)
in the memory-limited worker container, which is a tool limitation, not
corruption. Classify failures as encrypted | corrupt | inconclusive;
suppress notifications for inconclusive (debug log only) while still
proceeding with the upload as before. Genuine corruption now uses the
INTEGRITY_AUDIT notification type instead of the misleading HASH_MISMATCH;
encrypted archives still notify.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 08:57:25 +02:00
adminandClaude Opus 4.8 26bc43299a fix(telegram): make topics drawer scrollable + add topic title filter
The Radix ScrollArea viewport did not get a bounded height inside the
flex-column, max-h, vertically-centred dialog, so a long topic list
overflowed the dialog instead of scrolling (last topics unreachable).
Switch to a native flex-1 min-h-0 overflow-y-auto container, which is
the canonical touch-friendly flex-scroll pattern.

Also add a "Filter topics..." input (matches by topic title) so any
topic can be reached regardless of list length; reset the filter on
close; and add a toast fallback message on toggle failure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 08:50:10 +02:00
adminandClaude Opus 4.8 8b500a1610 feat(stls): enlarge candidate images in preview picker
continuous-integration/drone/push Build is passing
Each loaded candidate gets an enlarge button that opens the ImageLightbox
without changing selection, so the right preview is easier to choose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 04:57:40 +02:00
adminandClaude Opus 4.8 f0a9d3b4da feat(stls): click-to-enlarge preview in package files drawer
The drawer preview image opens the ImageLightbox; replacing the image
stays available via the existing Upload/Pick Preview buttons. No-preview
upload affordance unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 04:48:13 +02:00
adminandClaude Opus 4.8 b90317c007 feat(stls): click-to-enlarge package preview thumbnail in table
Package preview thumbnails open the ImageLightbox on click (hover shows a
maximize affordance). No-preview cells unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 04:44:52 +02:00
adminandClaude Opus 4.8 6f8ddcca81 feat(stls): add reusable ImageLightbox for full-size preview viewing
Radix Dialog-based lightbox (Esc / overlay / close button to dismiss),
image shown object-contain capped to the viewport. No new dependencies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 04:17:42 +02:00
adminandClaude Opus 4.8 25ff067ea0 feat(telegram): add Topics action to forum channels in Channels tab
Forum source channels get a Topics menu item that opens the TopicsDrawer.
Non-forum channels are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 04:15:46 +02:00
adminandClaude Opus 4.8 7e58cc29fa feat(telegram): add TopicsDrawer for per-topic fetch toggles
Lists a channel's topics with an enable/disable Switch each (optimistic,
revert on failure). Empty state explains topics appear after the next scan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 01:24:57 +02:00