feat(idempotency): postgres IdempotencyStore implementation
Implements eventsourced.IdempotencyStore (added in eventsourced v1.20.0) on the postgres event store:
- CheckIdempotency: look up cached event by (idempotency_key, aggregate_type, aggregate_id), respects expires_at
- StoreIdempotency: persists key + serialized event with TTL, ON CONFLICT DO NOTHING
- CleanupExpiredIdempotencyKeys: removes expired records
- New migration 20251101205358_add_idempotency.sql for command_idempotency table
Test plan:
- CheckIdempotency: not-found / found / query error / unknown type / invalid JSON / non-pointer aggregate
- StoreIdempotency: success / exec error / non-pointer aggregate / non-pointer event
- CleanupExpiredIdempotencyKeys: success / no rows / error / RowsAffected error
- reconstructIdempotentEvent: not reflect.Type / not Event branches
- Coverage 99.5% (above main's 99.3%)
See pg/IDEMPOTENCY.md for usage.