Skip to content

Latest commit

 

History

History
130 lines (117 loc) · 16.2 KB

File metadata and controls

130 lines (117 loc) · 16.2 KB

Notifications, Delivery & Alerts Spec

1. Spec Scope

1. This spec is canonical for the following outbound communication and notifications in behalf of users to their clients:

  1. manual invoice send flow
  2. paid receipts
  3. automated alert triggers
  4. shared delivery-log mechanics
  5. cooldown expectations and notice-class behavior

2. Goals

  1. Let invoice owners email a public link plus summary to their client from the app.
  2. Enable automatic, non-promissory payment acknowledgments and truthful owner-reviewed receipt emails.
  3. Support truthful alert emails when an invoice becomes past due or when on-chain payments deviate from the invoice total by more than the defined tolerance, including overpayment, underpayment, and partial-payment events.
  4. Keep payment-triggered mail truthful when the underlying payment state is semantically ambiguous, while still acknowledging what it safely can.

3. Base Communication Flows

  1. Send Invoice (manual owner action)

    1. Available when the invoice has a client email and its public link is enabled.
    2. Sending the invoice queues outbound delivery and records the attempt in the delivery log. If the invoice is currently in draft, the send action also transitions its status to sent. Sending an invoice that is already sent, partial, pending, paid, or void does not regress its status.
  2. Payment Acknowledgment + Receipt

    1. Detected Payment Acknowledgment
      1. When the system detects a Bitcoin payment with enough confidence to acknowledge it safely, it should send a low-information client acknowledgment before any later client receipt.
      2. This acknowledgment should confirm only what the system can safely say, such as the detected BTC amount, without claiming that the payment has been fully applied to a specific invoice state.
      3. The acknowledgment must remain non-promissory and should not imply that a receipt, refund, or other outcome is guaranteed.
      4. If the payment state is ambiguous, the acknowledgment should stay limited to what the system can safely say and should avoid any certainty about how the payment applies.
      5. When an acknowledgment is tied to a specific detected payment identity, repeated detection of that same payment must not create a second acknowledgment for the same notice class.
      6. The open beta uses paired owner/client delivery classes for this flow so the client acknowledgment and owner follow-through remain distinct in delivery history.
    2. Later Payment Ambiguity
      1. After an invoice has already received detected on-chain payment activity, later payments to that invoice’s address may still be semantically ambiguous even when the wallet configuration remains supported.
      2. Examples include stale-address reuse and payers intentionally using an older valid invoice address for a newer invoice.
      3. Later-payment ambiguity should narrow the acknowledgment to what the system can safely say rather than suppressing it outright.
    3. Receipt Follow-Up
      1. A receipt is a higher-certainty follow-up than an acknowledgment and should only be sent from an owner-reviewed payment state.
      2. The open beta does not auto-send client receipts from detected payment state alone, even when the invoice appears straightforward under current ledger rules.
      3. The product must support a clear owner-facing path to send that receipt after review and any needed ignore or reattribution work.
        1. That path should stay visible from the invoice payment history and from dashboard payment-review surfaces when a paid invoice still lacks a queued or sent client receipt.
      4. Later-payment ambiguity, ignore state, and reattribution state should surface truthful review context to the owner, but they are not the only reason a client receipt requires review.
      5. Requiring owner-reviewed client receipts must not suppress the owner paid notice or the owner-facing manual review/send path.
      6. RC1 policy (deliberate): Client receipts remain manual for RC1. This is a deliberate product decision — not a temporary incident constraint — chosen to capture real issuer behavior before committing to automation. Revisit after RC1 has been live for a reasonable period with real usage data (target: after at least 20–30 receipts sent manually in production, or after first production feedback cycle, whichever comes first).
  3. Delivery Log

    1. Outbound invoice communication should be recorded in a shared delivery history for audit and operator review.
    2. That history should cover manual sends, payment acknowledgments, receipts, and automated alerts.
    3. Owners should be able to review delivery outcomes, including queued, sent, skipped, and failed states.

4. Automated Alert Triggers

  1. Invoice Paid Notice (Owner)

    1. When an invoice becomes paid, the invoice issuer should receive a succinct owner notice.
    2. This notice should summarize the paid state, relevant payment details, and link back into the app for follow-up.
    3. The owner paid notice should remain distinct from any client-facing payment acknowledgment or receipt in the delivery history.
  2. Past Due (Owner + Client)

    1. When an invoice becomes past due and is still not paid or void, both the invoice issuer and the client should receive past-due reminders.
    2. The owner reminder should communicate that the invoice is overdue, include the outstanding totals, and suggest next steps.
    3. The client reminder should communicate the overdue status, include the outstanding balance and invoice link, and include a short “contact the sender if you already paid” caveat.
  3. Significant Overpayment Alert (Owner + Client)

    1. Triggered when the invoice reflects a significant overpayment (15% threshold for the open beta).
    2. The client alert should explain that overpayments are treated as gratuities by default and tell the client to contact the sender if the overpayment was accidental.
    3. The owner alert should report the overpayment percentage and prompt a disposition decision — keep as tip, credit the client, or record a manual adjustment/refund — with a link back into the app.
    4. The alert is judged against the client's payments only; an issuer ledger adjustment never triggers it and can only clear a pending one.
  4. Significant Underpayment Alert (Owner + Client)

    1. Triggered when the invoice still carries a significant remaining balance after payment activity (15% threshold for the open beta).
    2. The client alert should neutrally communicate that a balance remains, include the outstanding USD amount, and link to the public invoice so the client can settle; where appropriate, it may encourage completing the remaining balance in one payment for convenience.
    3. The owner alert should report the outstanding balance and link back to the invoice for follow-up or manual adjustment.
    4. Fragmented or repeated partial payments should not create a separate repeated-warning alert family; they should continue to use the final underpayment behavior instead.
    5. The alert requires a shortfall in the client's payments themselves; an issuer ledger adjustment (for example a reopened balance) never triggers it and can only clear a pending one.

5. Outbound Mail and History

  1. Outbound invoice communication should use a shared queued delivery path and shared delivery history so send outcomes remain auditable.
  2. The shared delivery history should preserve enough context to identify the invoice, sender/issuer context, recipient(s), communication class, outcome, and timing/error details for each outbound attempt.
  3. Public-share links embedded in outbound emails must use the explicitly configured public host for the intended recipient-facing environment.
    1. That public host may differ from the host currently running the app, such as when a development or staging environment is deliberately targeting another deployment.
  4. Client-facing payment-triggered notification emails should use explicit paired owner/client delivery classes for the open beta rather than relying on a generic issuer-copy toggle.
  5. Outbound mail capability is a required part of a valid recipient-facing deployment.
    1. Development and test environments may intentionally run without outbound mail, but production-ready deployments must have it configured.
  6. The shared delivery path must suppress duplicate or too-recent outbound attempts by notice class and record those suppressed attempts as skipped rather than silently dropping them.
  7. Outbound idempotency must be enforced at both delivery-intent creation and send execution so double clicks, concurrent processes, queue retries, or duplicate jobs do not produce duplicate outbound mail.
  8. Idempotency keys must be derived from stable business intent such as invoice, notice class, normalized recipient, and when applicable payment identity like txid, rather than rendered email bytes, provider-added headers, or variable timestamps in the subject/body.
  9. The outbound mail path must support an operator-controlled send-disable or circuit-breaker state that records attempted deliveries truthfully while outbound mail is disabled.
  10. Queued deliveries must revalidate current invoice truth before sending and mark the delivery skipped if the queued notice no longer matches the current recipient, public-share state, or payment state.
  11. The delivery history should surface queued, sending, sent, skipped, and failed outcomes.
  12. sending is the claimed provider-boundary state used to prevent duplicate job execution from producing a second outbound send while a delivery is already in progress or awaiting operator review after an ambiguous worker failure.
  13. The delivery history should use concise, human-friendly labels for communication classes and outcomes.
  14. Manual invoice sends should display as Invoice email, not a raw storage key.
  15. Paired issuer/client notification rows should keep the audience explicit in the label, such as Past-due reminder (client) and Underpayment alert (issuer).
  16. Payment-triggered follow-up should keep the acknowledgment-versus-receipt split visible in history once those rows ship, using labels such as Payment acknowledgment (client), Payment acknowledgment (owner), and Receipt (client) for the later higher-certainty follow-up.
  17. Outcome labels should display as Queued, Sending, Sent, Skipped, and Failed.
  18. Outbound mail copy should stay concise and actionable.
  19. Owner-facing mail-branding settings for the open beta may expose only constrained brand-shell controls, not arbitrary message editing.
  20. Allowed MS16 fields are limited to simple mail chrome values such as brand name, short tagline, footer blurb, and whether the default CryptoZing logo is shown in the shared mail header.
  21. Those settings should be prepopulated from the current shipped defaults so leaving them unchanged preserves the current mail output.
  22. Truthfulness-critical subjects and message bodies remain product-controlled in MS16, including payment acknowledgments, receipts, owner paid notices, and alert copy.
  23. The open beta may include a simple owner-facing send me a test email action that sends a branded test message to the authenticated owner account email using the current saved branding-shell settings.
    1. That preview should not send to client recipients or create invoice-linked delivery-history rows.
    2. That preview should be lightly rate-limited or cooldown-protected so repeated clicks do not spam the owner mailbox.
  24. The open beta does not include arbitrary custom logo uploads for outbound mail; at most it may show or hide the default CryptoZing logo in the shared mail chrome.
  25. Transient outbound send failures must be retried, not treated as terminal on the first failure.
  26. On a failed send attempt the delivery returns to a retryable state and the worker re-attempts under a bounded retry budget with spaced backoff, rather than being recorded failed immediately.
  27. A delivery is recorded as terminal failed only after the retry budget is exhausted, preserving the final error detail.
  28. Idempotency (items 7–8) must hold across all retry attempts: a transient failure followed by a successful retry produces exactly one outbound send and no duplicate delivery-history rows.
  29. A failed delivery must be operator-resendable for every notice class, not receipts alone.
  30. Resend reuses the shared delivery path and its cooldown/idempotency guards, so it recovers a failed notice without enabling a duplicate send of one already delivered.
  31. Every delivery must reach a truthful terminal state on its own.
  32. A delivery's recorded status must reflect the provider's actual handling: sent only if the provider accepted the message, failed if it did not.
  33. No delivery may remain indefinitely in a non-terminal state (queued/sending); it must resolve to sent or failed without operator intervention, including after a process crash or interruption mid-send.
  34. An already-sent invoice can be sent again on purpose from the invoice page. The control reads as a resend, the message goes out like a first send, and the delivery history records it as its own delivery.
  35. A short cooldown, minutes rather than hours, holds off accidental repeats, and the delivery history says so when it does.

Coverage & Status

One row per outbound notice class. Status: live = in production code, behaving per spec; stubbed = class exists but does not behave per spec (legacy or unwired); planned = named in spec, not yet implemented.

Audience Trigger Mailable class Status Feature test(s) Delivery log type
Client Manual owner action (issue invoice) InvoiceReadyMail live InvoiceDeliveryTest send
Client Detected on-chain payment (low-info ack) InvoicePaymentAcknowledgmentClientMail live InvoiceDeliveryTest, WatchPaymentsCommandTest payment_acknowledgment_client
Owner Detected on-chain payment (low-info ack) InvoicePaymentAcknowledgmentIssuerMail live InvoiceDeliveryTest, WatchPaymentsCommandTest payment_acknowledgment_issuer
Client Owner-reviewed manual receipt send (RC1 deliberate-manual) InvoicePaidReceiptMail live InvoiceDeliveryTest receipt
Owner Invoice transitions to paid InvoiceIssuerPaidNoticeMail live InvoiceNotificationTest, InvoiceDeliveryTest, WatchPaymentsCommandTest issuer_paid_notice
Owner Past-due schedule slot fires (slots 1/2/3 at days 1/7/14) InvoicePastDueIssuerMail live InvoiceNotificationTest past_due_issuer
Client Past-due schedule slot fires (slots 1/2/3 at days 1/7/14) InvoicePastDueClientMail live InvoiceNotificationTest past_due_client
Client Overpayment ≥15% threshold InvoiceOverpaymentClientMail live InvoiceNotificationTest client_overpay_alert
Owner Overpayment ≥15% threshold InvoiceOverpaymentIssuerMail live InvoiceNotificationTest issuer_overpay_alert
Client Underpayment ≥15% remaining InvoiceUnderpaymentClientMail live InvoiceNotificationTest client_underpay_alert
Owner Underpayment ≥15% remaining InvoiceUnderpaymentIssuerMail live InvoiceNotificationTest issuer_underpay_alert
Owner (self) Manual "send me a test email" preview action (§5.14.4) NotificationBrandingPreviewMail live MailBrandingTest — (no delivery-log row, per §5.14.4.1)