v0.1.0:43 — webhook DLQ, purchase trait migration, three more tests
Bumps version with release notes covering everything since v0.1.0:42: - Webhook DLQ: list + retry admin endpoints (operator-visible) - Purchase migrated onto PaymentProvider trait (internal refactor) - Tier-cap test, paid-purchase test, DLQ test - Test count 20 → 23 Straight drop-in upgrade from :42. No migrations, no schema changes.
This commit is contained in:
@@ -9,8 +9,31 @@
|
|||||||
import { VersionInfo } from '@start9labs/start-sdk'
|
import { VersionInfo } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
export const v0_1_0 = VersionInfo.of({
|
export const v0_1_0 = VersionInfo.of({
|
||||||
version: '0.1.0:42',
|
version: '0.1.0:43',
|
||||||
releaseNotes: [
|
releaseNotes: [
|
||||||
|
`Alpha-iteration revision 43 of v0.1.0 — Webhook delivery DLQ, purchase-flow refactor onto the PaymentProvider trait, and three more integration tests. Operator-visible: there's now an admin surface for inspecting and retrying failed outbound webhook deliveries.`,
|
||||||
|
``,
|
||||||
|
`**Webhook DLQ.** The delivery worker has always retried failed outbound webhooks with exponential backoff up to 10 attempts (5s, 10s, 30s, 1m, 5m, 15m, 30m, 1h, 2h, 6h), then set \`next_attempt_at = NULL\` and stopped. Until now, those "dead-lettered" rows sat in the database forever with no operator-facing surface — a subscriber endpoint that was down for >6h during a license-issuance burst silently lost those events. v0.1.0:43 adds:`,
|
||||||
|
``,
|
||||||
|
`\`\`\``,
|
||||||
|
`GET /v1/admin/webhook-deliveries?status=failed`,
|
||||||
|
`POST /v1/admin/webhook-deliveries/:id/retry`,
|
||||||
|
`\`\`\``,
|
||||||
|
``,
|
||||||
|
`The list endpoint accepts an optional \`endpoint_id\` filter, an optional \`status\` filter (\`pending\` | \`delivered\` | \`failed\` | \`all\`), and a \`limit\` (default 100, max 500). Newest-first ordering. The retry endpoint resets the row's attempt_count to 0, clears delivered_at + last_error, and sets next_attempt_at to now so the worker picks it up on the next 5s tick. Audit-logged as \`webhook_delivery.retry\`. The worker itself is unchanged; this is operator-actionable infrastructure on top of the existing retry semantics. The admin SPA will surface a "Failed deliveries" tab in v0.1.0:44+.`,
|
||||||
|
``,
|
||||||
|
`**Purchase flow migrated to the PaymentProvider trait.** \`purchase::start\` previously called \`state.btcpay_client().await?.create_invoice(amount, metadata, redirect)\` — the legacy compat path that downcasts the active provider specifically to the concrete \`BtcpayProvider\` type. It now calls \`state.payment_provider().await?.create_invoice(CreateInvoiceParams { ... })\` through the abstract trait. Provider-specific concerns (BTCPay's checkout-URL host rewriting from the internal Docker hostname to the public domain, metadata enrichment with \`orderId\`/\`source\`) move inside the BtcpayProvider impl where they belong; the same call path now serves any future provider (Zaprite in v0.3, etc.) without fork/copy. No buyer-visible change; same checkout URLs, same invoice ids.`,
|
||||||
|
``,
|
||||||
|
`**Three new integration tests.** Test count: 23 (9 unit + 4 migration + 10 API), up from 20 in v0.1.0:42.`,
|
||||||
|
``,
|
||||||
|
` - \`tier_caps_block_at_creator_limit_and_unlock_after_upgrade\` — verifies the 402 PAYMENT_REQUIRED gate on \`/v1/admin/products\` fires at the Creator-tier product cap (5), and that swapping \`self_tier\` to a Licensed tier with \`unlimited_products\` lifts the cap without a daemon restart. Mirrors what the admin UI's "Activate Keysat license" flow does. The 402 carries \`upgrade_url\` so the SPA can render the upgrade CTA inline.`,
|
||||||
|
``,
|
||||||
|
` - \`paid_purchase_creates_invoice_via_provider\` — previously deferred per :42's release notes because the legacy compat path prevented MockPaymentProvider from substituting. The trait migration above unblocks it. Verifies the daemon delegates invoice creation to the provider, the returned provider_invoice_id is stamped on the local invoice row, the buyer-facing checkout_url is whatever the provider returned, and no license is issued before the settle webhook fires.`,
|
||||||
|
``,
|
||||||
|
` - \`webhook_dlq_lists_failed_and_retry_requeues\` — seeds three deliveries directly via SQL (one each: delivered, pending, dead-lettered), exercises the new list filter, runs the retry, asserts the row migrates from \`failed\` → \`pending\`, the audit row is written, 404 on bad id, 400 on bad status filter.`,
|
||||||
|
``,
|
||||||
|
`**Upgrade path.** v0.1.0:42 → v0.1.0:43 is a straight drop-in. No new migrations, no schema changes, no behavior changes for buyers. Operators gain the new \`/v1/admin/webhook-deliveries\` endpoints; the admin SPA doesn't yet surface them but \`curl\` + an admin API key works today.`,
|
||||||
|
``,
|
||||||
`Alpha-iteration revision 42 of v0.1.0 — Test infrastructure expansion. No daemon-behaviour changes for operators; this release ships safety nets for future development. Skip if v0.1.0:41 is running cleanly — the next release with new functionality will roll forward whatever shipped here.`,
|
`Alpha-iteration revision 42 of v0.1.0 — Test infrastructure expansion. No daemon-behaviour changes for operators; this release ships safety nets for future development. Skip if v0.1.0:41 is running cleanly — the next release with new functionality will roll forward whatever shipped here.`,
|
||||||
``,
|
``,
|
||||||
`**API integration tests.** New \`tests/api.rs\` with seven integration tests that drive real HTTP requests through the daemon's \`axum::Router\` against a real SQLite tempfile. Covers: health endpoint, admin auth (401 vs 403 paths), admin product creation (full happy path: auth → handler → DB → audit log → response), license validation (parse-fail surface plus full crypto round-trip), free-tier purchase with inline license issuance, and BTCPay webhook idempotency (re-delivered settle webhooks MUST NOT duplicate the license — the production-correctness invariant we most needed to lock down).`,
|
`**API integration tests.** New \`tests/api.rs\` with seven integration tests that drive real HTTP requests through the daemon's \`axum::Router\` against a real SQLite tempfile. Covers: health endpoint, admin auth (401 vs 403 paths), admin product creation (full happy path: auth → handler → DB → audit log → response), license validation (parse-fail surface plus full crypto round-trip), free-tier purchase with inline license issuance, and BTCPay webhook idempotency (re-delivered settle webhooks MUST NOT duplicate the license — the production-correctness invariant we most needed to lock down).`,
|
||||||
|
|||||||
Reference in New Issue
Block a user