Part of #8 (M2 epic). The scale-up provider. Ships EF migrations → risk:critical (migration-safety review on the PR).
Acceptance criteria
IMessageStore + IEndpointStore on Postgres via EF Core, with shipped, reviewed migrations for the messages/endpoints schema (no ensure-created in production).
- Claim path uses
SELECT ... FOR UPDATE SKIP LOCKED so N dispatchers claim disjoint batches with no contention and no double-send.
- Same
IMessageStore contract + semantics as the SQLite/in-memory tiers (the M1 benchmark on ClaimDueAsync is the reference for the SQL push-down).
- One-line opt-in (
AddCaliberWebhooks(o => o.UsePostgres(...)) / UseEntityFramework<AppDbContext>()), guarantee tier explicit.
Definition of done
- Builds net8.0 + net10.0, zero warnings; migration SQL reviewed for safety; integration tests (see the Testcontainers issue) prove no-double-send; docs reconciled.
Design: docs/design/caliber-webhooks-core-design.md §Work-claiming data model • concepts/storage-and-work-claiming.md • roadmap M2. Depends on the SQLite store shaping the contract.
Part of #8 (M2 epic). The scale-up provider. Ships EF migrations →
risk:critical(migration-safety review on the PR).Acceptance criteria
IMessageStore+IEndpointStoreon Postgres via EF Core, with shipped, reviewed migrations for themessages/endpointsschema (no ensure-created in production).SELECT ... FOR UPDATE SKIP LOCKEDso N dispatchers claim disjoint batches with no contention and no double-send.IMessageStorecontract + semantics as the SQLite/in-memory tiers (the M1 benchmark onClaimDueAsyncis the reference for the SQL push-down).AddCaliberWebhooks(o => o.UsePostgres(...))/UseEntityFramework<AppDbContext>()), guarantee tier explicit.Definition of done
Design: docs/design/caliber-webhooks-core-design.md §Work-claiming data model • concepts/storage-and-work-claiming.md • roadmap M2. Depends on the SQLite store shaping the contract.