The tables purgeExpiredThreads deletes from under the thread TTL — the
production anchor the schema guard cross-checks the thread-ttl retention
declaration against, AND the target set a cascade child must appear in to be
believed. Both tables are here because the purge reaps a thread and
its messages together: mastra_threads by its own updatedAt,
mastra_messages by cascade (a message has no idleness signal of its own — see
the purge doc). So the inventory's mastra_messages: { retention: cascade with mastra_threads } is only legal because mastra_messages is genuinely a delete
target here; a cascade naming a parent whose purge never touches the child is
the lie the guard now catches.
The tables
purgeExpiredThreadsdeletes from under the thread TTL — the production anchor the schema guard cross-checks thethread-ttlretention declaration against, AND the target set acascadechild must appear in to be believed. Both tables are here because the purge reaps a thread and its messages together:mastra_threadsby its ownupdatedAt,mastra_messagesby cascade (a message has no idleness signal of its own — see the purge doc). So the inventory'smastra_messages: { retention: cascade with mastra_threads }is only legal becausemastra_messagesis genuinely a delete target here; a cascade naming a parent whose purge never touches the child is the lie the guard now catches.