fix(inbox): separate automatic recovery cleanup from user participation

Keep exact workspace owner verification holds stable and let sandbox agents inspect authorized issue activity.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Devin FoleyandPaperclip committed 2026-10-12 17:40:07 -07:00
1 parent 4b958ecbd8
commit 697e132ca4
13 files changed
+194 -8

No files matched your search

+13
View File
@@ -2834,6 +2834,16 @@ const ISSUE_USER_PARTICIPATION_ACTIVITY_ACTIONS = [
"issue.work_product_updated",
] as const;
// Old read projections attributed this automatic cleanup to the reader. Keep
// the audit rows, but do not count them as participation or issue activity.
function automaticReadRecoveryCleanupCondition() {
return sql<boolean>`(
${activityLog.action} = 'issue.recovery_action_resolved'
AND COALESCE(${activityLog.details}->>'source', '') = 'source_revalidation'
AND COALESCE(${activityLog.details}->>'trigger', '') = 'read_projection'
)`;
}
function touchedByUserCondition(companyId: string, userId: string) {
return sql<boolean>`
(
@@ -2847,6 +2857,7 @@ function touchedByUserCondition(companyId: string, userId: string) {
AND ${activityLog.companyId} = ${companyId}
AND ${activityLog.actorType} = 'user'
AND ${activityLog.actorId} = ${userId}
AND NOT ${automaticReadRecoveryCleanupCondition()}
AND ${activityLog.action} IN (${sql.join(
ISSUE_USER_PARTICIPATION_ACTIVITY_ACTIONS.map(
(action) => sql`${action}`,
@@ -2952,6 +2963,7 @@ function issueLatestLogAtExpr(companyId: string) {
WHERE ${activityLog.companyId} = ${companyId}
AND ${activityLog.entityType} = 'issue'
AND ${activityLog.entityId} = ${issues.id}::text
AND NOT ${automaticReadRecoveryCleanupCondition()}
AND ${activityLog.action} NOT IN (${sql.join(
ISSUE_LOCAL_INBOX_ACTIVITY_ACTIONS.map((action) => sql`${action}`),
sql`, `,
@@ -5127,6 +5139,7 @@ async function lastActivityStatsForIssues(
eq(activityLog.companyId, companyId),
eq(activityLog.entityType, "issue"),
inArray(activityLog.entityId, issueIdChunk),
sql`NOT ${automaticReadRecoveryCleanupCondition()}`,
sql`${activityLog.action} NOT IN (${sql.join(
ISSUE_LOCAL_INBOX_ACTIVITY_ACTIONS.map(
(action) => sql`${action}`,