The retention purge job gated its whole body on activeRetention while every collection declares only postDeletion, and no app ever called registerRetentionPurgeJobs — retention was dead end to end (audit findings A2 + A3). The DSR soft delete now stamps a deletedAt tombstone on postDeletion collections (kept distinct from processingRestrictedAt so an Art. 18 restriction never feeds the purge), the job grace-purges tombstoned rows past postDeletion.duration with the declared action, core-cms injects the tombstone field + Payload task definitions, and bindAllProduction enqueues the first purge cycle at boot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
import type { Payload } from "payload";
|
|
import { PayloadJobQueue } from "../../jobs/payload-job-queue";
|
|
import { buildPurgeHandler, type PayloadPurgeApi } from "./retention-purge.job";
|
|
|
|
/**
|
|
* Minimal shape of a Payload job-task definition — enough for
|
|
* `payload.config.ts` `jobs.tasks` composition without dragging the full
|
|
* generated TaskConfig generics through core-shared.
|
|
*/
|
|
export type RetentionPurgeTask = {
|
|
slug: string;
|
|
handler: (args: { req: { payload: Payload } }) => Promise<{
|
|
output: Record<string, never>;
|
|
}>;
|
|
};
|
|
|
|
/**
|
|
* Build the Payload job-task definition for one collection's retention purge
|
|
* (audit finding A3): `registerRetentionPurgeJobs` enqueues
|
|
* `retention-purge--<slug>` tasks at boot, and this definition is what makes
|
|
* Payload able to RUN them. Everything the handler needs comes from the
|
|
* running instance on `req.payload` (config, local API, job queue for the
|
|
* self-re-enqueue), so the task can be declared at config-composition time
|
|
* with no bootstrapping order problems.
|
|
*/
|
|
export function buildRetentionPurgeTask(
|
|
collectionSlug: string,
|
|
): RetentionPurgeTask {
|
|
return {
|
|
slug: `retention-purge--${collectionSlug}`,
|
|
handler: async ({ req }) => {
|
|
const payload = req.payload;
|
|
const run = buildPurgeHandler(collectionSlug, {
|
|
queue: new PayloadJobQueue(payload),
|
|
config: payload.config,
|
|
getPayload: async () => payload as unknown as PayloadPurgeApi,
|
|
});
|
|
await run();
|
|
return { output: {} };
|
|
},
|
|
};
|
|
}
|