tombstone gate all user paths; cleanup deletes late follower rows; spa self-delete to /; adr 0016 + purge comment

This commit is contained in:
2026-10-26 03:22:13 +01:00
parent caab63596a
commit b9cdb54340
7 changed files with 63 additions and 10 deletions

View File

@@ -223,6 +223,16 @@ impl AccountPurger for SqliteAccountPurger {
.execute(&mut *tx)
.await
.map_err(map_sqlx_error)?;
// A Follow arriving on the shared inbox after the purge can leave
// a late row for the tombstone; delete it explicitly rather than
// rely on the foreign-key cascade of the final `users` delete.
for table in ["ap_followers", "ap_following"] {
sqlx::query(&format!("DELETE FROM {table} WHERE local_user_id = ?"))
.bind(id)
.execute(&mut *tx)
.await
.map_err(map_sqlx_error)?;
}
for table in RETAINED_USER_TABLES {
sqlx::query(&format!("DELETE FROM {table} WHERE user_id = ?"))
.bind(id)

View File

@@ -696,6 +696,14 @@ async fn tombstone_cleanup_removes_rows_older_than_retention_and_keeps_younger_o
assert_eq!(count_for(&pool, "users", "id", &s.user).await, 1);
assert_eq!(unfinished().await, before);
// A Follow that reached the shared inbox after the purge left a row.
exec(
&pool,
"INSERT INTO ap_followers (local_user_id, remote_actor_url, status, created_at)
VALUES (?, 'https://late.example/users/zed', 'pending', '2026-01-01T00:00:00Z')",
&[&alice],
)
.await;
// Once they finish, the cleanup takes the tombstone and the history.
exec(&pool, "UPDATE event_queue SET status = 'done'", &[]).await;
let removed = p
@@ -712,6 +720,11 @@ async fn tombstone_cleanup_removes_rows_older_than_retention_and_keeps_younger_o
left.iter().all(|p| !p.contains(&alice)),
"no history of the user remains: {left:?}"
);
assert_eq!(
count_for(&pool, "ap_followers", "local_user_id", &s.user).await,
0,
"late shared-inbox follower row"
);
assert_eq!(
count_for(&pool, "ap_local_actors", "user_id", &s.user).await,
0