ReviewOS

stacks/bun-query-builder

ORM: soft deletes never filter reads — deleted rows leak into get/find/count/paginate

#1024
Closed glennmichael123 opened this 22 days ago · 0 comments
22 days ago

Summary

The useSoftDeletes trait adds a deleted_at column and ModelInstance.delete() correctly sets it, but ModelQueryBuilder never appends deleted_at IS NULL to reads. Every query().get(), find(), count(), paginate(), aggregate, and eager-load returns soft-deleted rows. There is also no withTrashed / onlyTrashed / restore.

Evidence (repro, sqlite)

after p2.delete(): Post.query().get() -> 2 rows ["A","B"]; Post.query().count() -> 2

The deleted row is still returned.

Location

src/orm.tsbuildQuery() (~1888), count() (~2107), aggregate, pluck, and the eager-load paths.

Suggested fix

When definition.traits?.useSoftDeletes (or its softDeletable alias) is set, auto-inject deleted_at IS NULL into all read SQL, and add withTrashed() / onlyTrashed() / restore().

Severity: high (core trait silently broken). Found via internal code audit.

Sign in to comment on this issue.