Drop buyer email/SMTP from roadmap; reframe as StartOS operator alerts
Operators selling via Keysat own their buyer-email path through their own app plus the existing webhook delegation, so a Keysat-side SMTP send path is redundant and a branding/double-send liability. The surviving need -- operator visibility into failures where the webhook channel itself is what's broken (dead-lettered endpoint, revoked provider key, expiring license) -- is re-homed onto StartOS notifications/health checks rather than a mailer Keysat ships.
This commit is contained in:
+18
-1
@@ -4,7 +4,6 @@ Longer-term backlog. Near-term state lives in `AGENTS.md` → Current state.
|
|||||||
|
|
||||||
## Payments & subscriptions
|
## Payments & subscriptions
|
||||||
|
|
||||||
- Per-profile SMTP override (schema fields exist from the keysat-smtp-emails plan; needs the form + send path).
|
|
||||||
- Rail-preference editing UI — only matters when two providers on one profile both serve the same rail; settable today via `PUT /v1/admin/merchant-profiles/:id/rail-preferences/:rail`.
|
- Rail-preference editing UI — only matters when two providers on one profile both serve the same rail; settable today via `PUT /v1/admin/merchant-profiles/:id/rail-preferences/:rail`.
|
||||||
- **Auto-charge silently lapses a subscription on a 200-with-failure response (money-path bug; elevated above the other parked payments items).** `try_auto_charge_zaprite` returns `Ok(true)` on *any* HTTP 2xx (`subscriptions.rs:1403-1410`), reading the order `status` only for a log line. If Zaprite returns 200 carrying a `FAILED`/`DECLINED`/`EXPIRED` order status, the daemon fires `auto_charge_initiated` and then waits for an `order.paid` webhook that never arrives — the subscription silently lapses, no error surfaced, the customer churns. Safe fix (no production data needed): treat any non-`PAID` terminal order status as not-success and fall through to the manual-pay path — a conservative fail-safe, ~10 lines + a mock-provider test. (Found during the 2026-06-17 adjudication; it replaces the old "harden Zaprite failure-body shapes" item, which was already satisfied for non-2xx responses — those route correctly to WARN + `auto_charge_failed` audit + webhook + manual-pay fallback.)
|
- **Auto-charge silently lapses a subscription on a 200-with-failure response (money-path bug; elevated above the other parked payments items).** `try_auto_charge_zaprite` returns `Ok(true)` on *any* HTTP 2xx (`subscriptions.rs:1403-1410`), reading the order `status` only for a log line. If Zaprite returns 200 carrying a `FAILED`/`DECLINED`/`EXPIRED` order status, the daemon fires `auto_charge_initiated` and then waits for an `order.paid` webhook that never arrives — the subscription silently lapses, no error surfaced, the customer churns. Safe fix (no production data needed): treat any non-`PAID` terminal order status as not-success and fall through to the manual-pay path — a conservative fail-safe, ~10 lines + a mock-provider test. (Found during the 2026-06-17 adjudication; it replaces the old "harden Zaprite failure-body shapes" item, which was already satisfied for non-2xx responses — those route correctly to WARN + `auto_charge_failed` audit + webhook + manual-pay fallback.)
|
||||||
## Agent compatibility & scoped API keys
|
## Agent compatibility & scoped API keys
|
||||||
@@ -36,6 +35,24 @@ Longer-term backlog. Near-term state lives in `AGENTS.md` → Current state.
|
|||||||
Submission criteria themselves remain unpublished; reach out to Start9 when ready. (Icon-render and the
|
Submission criteria themselves remain unpublished; reach out to Start9 when ready. (Icon-render and the
|
||||||
source-available license are intentionally not treated as blockers.)
|
source-available license are intentionally not treated as blockers.)
|
||||||
|
|
||||||
|
## Operability & alerts
|
||||||
|
|
||||||
|
- **Surface internal failure conditions to the operator via StartOS-native notifications / health checks** —
|
||||||
|
NOT a bespoke email/SMTP subsystem. The need is real and not covered by the webhook-delegation model: when
|
||||||
|
the failure IS the webhook path (a dead-lettered endpoint, or the operator's receiver being down), a webhook
|
||||||
|
can't report it, and the operator's own email pipeline is downstream of the same webhooks. So Keysat must own
|
||||||
|
an out-of-band operator-visible channel — and on StartOS that channel is the OS notification/health surface,
|
||||||
|
not a mailer Keysat ships itself. Conditions worth alerting on (the surviving kernel of the dropped email plan):
|
||||||
|
payment-provider auth dead (repeated 401s ⇒ key revoked/rotated), a webhook endpoint hitting dead-letter,
|
||||||
|
master self-license expiring-soon / expired, and (optional) renewals failing across the pool. The health-check
|
||||||
|
path is already wired; verify the `start-sdk` 1.3.2 notification API before committing to a delivery mechanism.
|
||||||
|
Background + the original alert catalog (Tier 1/2/3, throttling) live in the superseded
|
||||||
|
`plans/keysat-smtp-emails.md`. **Buyer-facing email and the per-profile SMTP send path are dropped** (decided
|
||||||
|
2026-06-18): operators selling via Keysat already own their buyer relationship and email pipeline through their
|
||||||
|
own app + the existing webhooks, so Keysat emailing buyers is redundant and a branding/double-send liability.
|
||||||
|
The dormant `merchant_profiles.smtp_*` columns (migration 0020) are now dead weight — left in place (a removal
|
||||||
|
migration isn't worth it) and flagged in `src/merchant_profiles.rs`.
|
||||||
|
|
||||||
## Licensing model
|
## Licensing model
|
||||||
|
|
||||||
- Evaluate Elastic License v2 vs the current custom `LicenseRef-Keysat-1.0` (parked decision).
|
- Evaluate Elastic License v2 vs the current custom `LicenseRef-Keysat-1.0` (parked decision).
|
||||||
|
|||||||
Reference in New Issue
Block a user