540151290b
A one-shot Maintenance action to remove the blurred locked-preview images the ingester downloaded from tier-gated Patreon posts before #874. current_user_can_view was never persisted, so the cleanup re-walks each enabled Patreon source (read-only) to re-derive which posts are gated now and the blurred filehashes Patreon serves for them, then matches by CONTENT HASH against stored source_filehash. Because the hash is content-addressed, a real file downloaded when access existed has a different hash and can never match — regained-then-lost-access content is provably spared (operator's hard requirement). NULL source_filehash => unverifiable, kept + reported. On apply: delete matched ImageRecords + files (provenance cascades), clear seen/dead-letter ledger rows for those hashes so the real media re-ingests if access returns, and delete gated posts left bare. Shares one match predicate between preview and apply (rule 93). - cleanup_service: collect_gated_previews + purge_gated_previews - tasks.admin: purge_gated_previews_task (async re-walk bridge, timeboxed) - api.admin: POST /maintenance/purge-gated-previews - GatedPurgeCard.vue in Settings > Maintenance (preview -> confirm -> apply) - tests: collect predicate, hash-match delete/spare/unverifiable, ledger clear, bare-post removal, no-op Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
70 lines
2.4 KiB
Vue
70 lines
2.4 KiB
Vue
<template>
|
|
<div class="fc-maint">
|
|
<p class="text-body-2 mb-4">
|
|
Operational backfills and tagging controls. The ML backfill and centroid
|
|
recompute run nightly automatically; the allowlist auto-applies accepted
|
|
tags to new and existing images. Use the cards below to trigger a
|
|
one-off pass.
|
|
</p>
|
|
<div class="fc-maint__grid">
|
|
<MLBackfillCard />
|
|
<CentroidRecomputeCard />
|
|
<ThumbnailBackfillCard />
|
|
</div>
|
|
<MLThresholdSliders class="mt-4" />
|
|
<AllowlistTable class="mt-4" />
|
|
<AliasTable class="mt-4" />
|
|
<DbMaintenanceCard class="mt-6" />
|
|
<ArchiveReextractCard class="mt-6" />
|
|
<MissingFileRepairCard class="mt-6" />
|
|
<VideoDedupCard class="mt-6" />
|
|
<GatedPurgeCard class="mt-6" />
|
|
<BackupCard class="mt-6" />
|
|
<!-- TagMaintenanceCard moved to Cleanup tab (v26.05.25.7) — it
|
|
operates on the existing library which fits the Cleanup-tab
|
|
theme, and clusters with the other audit cards. LegacyMigrationCard
|
|
removed once the one-and-done GS/IR migration cutover completed. -->
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, onUnmounted } from 'vue'
|
|
|
|
import MLBackfillCard from './MLBackfillCard.vue'
|
|
import CentroidRecomputeCard from './CentroidRecomputeCard.vue'
|
|
import ThumbnailBackfillCard from './ThumbnailBackfillCard.vue'
|
|
import MLThresholdSliders from './MLThresholdSliders.vue'
|
|
import AllowlistTable from './AllowlistTable.vue'
|
|
import AliasTable from './AliasTable.vue'
|
|
import DbMaintenanceCard from './DbMaintenanceCard.vue'
|
|
import ArchiveReextractCard from './ArchiveReextractCard.vue'
|
|
import MissingFileRepairCard from './MissingFileRepairCard.vue'
|
|
import VideoDedupCard from './VideoDedupCard.vue'
|
|
import GatedPurgeCard from './GatedPurgeCard.vue'
|
|
import BackupCard from './BackupCard.vue'
|
|
import { useSystemActivityStore } from '../../stores/systemActivity.js'
|
|
|
|
// Poll queue depths so each card's QueueStatusBar shows live pending
|
|
// counts — the operator can see a backfill is already queued/running
|
|
// before re-triggering it.
|
|
const activity = useSystemActivityStore()
|
|
let qTimer = null
|
|
onMounted(() => {
|
|
activity.loadQueues()
|
|
qTimer = setInterval(() => {
|
|
if (!document.hidden) activity.loadQueues()
|
|
}, 4000)
|
|
})
|
|
onUnmounted(() => {
|
|
if (qTimer) { clearInterval(qTimer); qTimer = null }
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.fc-maint__grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
gap: 16px;
|
|
}
|
|
</style>
|