Current state
The spec declares soft-delete capability in two places, but neither has any behavior-changing reader — every delete today is a physical hard delete at the driver level.
enable.trash (default true, described as "Enable soft-delete with restore capability") — packages/spec/src/data/object.zod.ts (~L110)
SoftDeleteConfigSchema (enabled / field: 'deleted_at' / cascadeDelete) — packages/spec/src/data/object.zod.ts (~L288)
- The permission model also reserves a Restore (soft-delete recovery) semantic (
packages/spec/src/security/permission.zod.ts)
The June 2026 liveness audit (docs/audits/2026-06-objectschema-property-liveness.md) confirms:
trash is one of the 10 flags with zero behavior-changing readers in either repo; softDelete ↔ enable.trash — duplicated, both dead.
The default trash: true is actively misleading: schema authors reasonably assume deleted records are recoverable, but they are gone.
Note: deleted_at on some identity objects (e.g. sys_user) is a better-auth convention local to those objects, not a platform mechanism.
Proposal
Implement platform-level soft delete honoring the existing spec surface:
- Delete path: when soft delete is enabled for an object,
delete stamps the configured timestamp field (default deleted_at) instead of removing the row.
- Query path: default-scope all reads to exclude soft-deleted rows; provide an explicit opt-in to include/only-trashed (recycle-bin views).
- Restore: a restore operation clearing the marker, gated by the reserved Restore permission.
- Purge: a real (physical) delete for emptying the trash, plus optional retention/TTL via the ADR-0057 LifecycleService.
- Cascade: honor
cascadeDelete for related records (or explicitly descope it for v1).
- Spec reconciliation: collapse the duplicated
enable.trash vs softDelete surface into one canonical config (and fix the misleading trash: true default until the runtime actually enforces it).
Open questions: interaction with unique indexes (soft-deleted rows still occupy unique keys), lookup integrity when a target is trashed, and REST/console surface for the recycle bin.
Current state
The spec declares soft-delete capability in two places, but neither has any behavior-changing reader — every delete today is a physical hard delete at the driver level.
enable.trash(defaulttrue, described as "Enable soft-delete with restore capability") —packages/spec/src/data/object.zod.ts(~L110)SoftDeleteConfigSchema(enabled/field: 'deleted_at'/cascadeDelete) —packages/spec/src/data/object.zod.ts(~L288)packages/spec/src/security/permission.zod.ts)The June 2026 liveness audit (
docs/audits/2026-06-objectschema-property-liveness.md) confirms:The default
trash: trueis actively misleading: schema authors reasonably assume deleted records are recoverable, but they are gone.Note:
deleted_aton some identity objects (e.g.sys_user) is a better-auth convention local to those objects, not a platform mechanism.Proposal
Implement platform-level soft delete honoring the existing spec surface:
deletestamps the configured timestamp field (defaultdeleted_at) instead of removing the row.cascadeDeletefor related records (or explicitly descope it for v1).enable.trashvssoftDeletesurface into one canonical config (and fix the misleadingtrash: truedefault until the runtime actually enforces it).Open questions: interaction with unique indexes (soft-deleted rows still occupy unique keys), lookup integrity when a target is trashed, and REST/console surface for the recycle bin.