Spectro 2.0 focuses on PostgreSQL correctness and application-level validation. It also includes the changeset, pagination, and soft-delete APIs added since 1.2.0.
Breaking changes
- Custom
Repoconformers must implementinsert(_ changeset:)andupdate(_ changeset:). Spectro's built-in repositories already implement both requirements, including inside transactions. - Model-returning right joins now throw because their result types cannot represent an absent main model. Reverse the query and use a left join. Typed self joins and repeated tables are rejected until table aliases are supported; typed left joins require a nonnullable primary key on the joined schema.
- Typed joined reads now throw when a present row cannot be decoded, instead of substituting default values or silently omitting it.
- Migration runners require a direct or session-pooled connection and transaction-compatible SQL. Use the 2.0 runner consistently when multiple processes can migrate the same database.
See the upgrade guide for migration examples and operational changes.
Added
- Changesets with permitted-field casting, validators, serializable errors, uniqueness checks, and repository insert/update support.
Query.page(size:page:)with total counts and navigation metadata.- Opt-in soft deletes with
@SoftDeleteand.withDeleted(). - A public-API IssueTracker HTTP application and repeatable acceptance command covering transactions, joined reads, competing writes, populated migrations, rollback/reapply, and restart persistence.
Fixed
@Schemarecognizes@SoftDelete, generates filtering metadata, and preserves deletion timestamps in decoded models and JSON.- Migration SQL and status recording now use the same transaction. Competing migration commands serialize through a PostgreSQL advisory lock, with bounded lock waiting and cancellation cleanup.
- Joined models decode from separate projections, preserving IDs, timestamps, custom column mappings, and nullable fields without column collisions. An unmatched left-joined model is
nil. - Query parameters follow SQL order across joins, filters, and HAVING clauses; soft-delete filters are qualified in joined queries.
- Changeset casting rejects invalid field types and non-finite numbers before persistence. Both repositories honor custom column names.
- Recursive error formatting no longer crashes when reporting
SpectroError; transaction failures preserve the original error after successful rollback. - Database connections honor configured TLS settings and reject invalid settings before allocating event-loop threads.
- Fresh-database migration commands initialize their tracking state, while migration status remains read-only.
- CI propagates test failures. Acceptance build artifacts use a local cache to avoid macOS signing failures caused by Finder metadata in cloud-synced folders.
Compatibility and validation
- Spectro requires Swift 6.0+ and supports macOS 13+ and Linux with PostgreSQL.
- All 368 PostgreSQL-backed tests passed on macOS and Linux with Swift 6.0.3, including concurrent migration processes, cancellation, and macro-defined soft deletes. HTTP acceptance passed with Swift 6.3.3 and Xcode 26.3. CI verification.
- Building the IssueTracker acceptance application requires Swift 6.3+ and an Xcode 26.3+ SDK on a compatible host (macOS 15.6+ for Xcode 26.3); its package deployment target is macOS 14. Its pinned Peregrine 1.2.0 dependency currently prevents that example from building on Linux; Spectro's core Linux support is unaffected.