mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 15:31:38 +02:00
feat(premium): recurring tiered relay-posting subscription (premium-post)
A paid premium tier gating GENERAL Nostr posting to the operator's relay, while
wallet-functional events (encrypted DMs, tips, swap coordination) stay free for
registered users. Registration itself stays free (PoW-gated). Off by default.
- Admission: a new `premium-post` write policy gates on kind x membership —
premium author -> any kind; registered + WALLET_KINDS (1059 gift-wrap, 10050
DM-relay-list) -> free; registered + general -> premium required; external ->
gift-wrap DM inbox only. nauthz resolves is_premium_npub (only under premium-post),
fail-closed.
- Payment: reuses the PaymentProvider seam (PULL model, non-custodial — only reads
invoice status). POST /premium/invoice {plan} mints a tier invoice bound to the
JWT user_id; POST /premium/activate verifies Settled + consumes single-use AND
extends premium_until in ONE transaction (a mid-flight failure keeps the paid
invoice redeemable); GET /premium/status reads it. Per-user pending-invoice cap.
- Tiered plans (PREMIUM_PLANS id:days:amount) = a built-in discount feature;
advertised via /capabilities (premium_relay + premium{currency,plans,relay_url}).
- Config fail-closes: PREMIUM_ENABLED needs relay on + premium-post + processor
creds + >=1 positive-decimal plan + unique ids + days<=3660, and the 0-conf /
expiry processor floors apply on the premium path too (its common case is
require_payment=false).
- Tests: 15 policy unit (incl. 5 premium-post) + config fail-closed matrix + plan
parser + L1 integration (activate single-use/stacking/cross-user, is_premium by
expiry, feature gate). OpenAPI + migration updated.
Adversarially reviewed (correctness / security-payment / operational-config); the
0-conf-on-premium-path double-spend footgun, non-transactional activate, and
unbounded plan days were caught and fixed before commit.
This commit is contained in:
+11
-1
@@ -62,6 +62,9 @@ use utoipa::OpenApi;
|
||||
crate::api::wallet::grin_relay::cancel,
|
||||
crate::api::wallet::heights::heights,
|
||||
crate::api::nip05::well_known_nostr,
|
||||
crate::api::premium::invoice,
|
||||
crate::api::premium::activate,
|
||||
crate::api::premium::status,
|
||||
),
|
||||
components(schemas(
|
||||
crate::api::health::HealthResponse,
|
||||
@@ -72,6 +75,8 @@ use utoipa::OpenApi;
|
||||
crate::api::capabilities::RestoreCapability,
|
||||
crate::api::capabilities::RegistrationCapability,
|
||||
crate::api::capabilities::MessagingCapability,
|
||||
crate::api::capabilities::PremiumCapability,
|
||||
crate::api::capabilities::PremiumPlanInfo,
|
||||
crate::api::prices::PricesResponse,
|
||||
crate::api::auth::AuthResponse,
|
||||
crate::api::auth::UserInfo,
|
||||
@@ -143,6 +148,10 @@ use utoipa::OpenApi;
|
||||
crate::api::wallet::grin_relay::PendingRelaysResponse,
|
||||
crate::api::wallet::heights::HeightsResponse,
|
||||
crate::api::nip05::WellKnownResponse,
|
||||
crate::api::premium::InvoiceReq,
|
||||
crate::api::premium::InvoiceResp,
|
||||
crate::api::premium::ActivateReq,
|
||||
crate::api::premium::StatusResp,
|
||||
)),
|
||||
tags(
|
||||
(name = "system", description = "Service health and metadata."),
|
||||
@@ -151,7 +160,8 @@ use utoipa::OpenApi;
|
||||
(name = "btc_ltc", description = "Bitcoin/Litecoin chain access via Electrum (balance, UTXOs, history, tip, fee, broadcast)."),
|
||||
(name = "xmr_wow", description = "Monero/Wownero chain access via LWS (register, balance, history, unspent/random outs, submit, height, confirmations)."),
|
||||
(name = "grin", description = "Grin view-only chain access (rewind_hash scan, tip height, broadcast)."),
|
||||
(name = "grin_relay", description = "Grin slatepack relay: async non-custodial mailbox for interactive Grin transfers (feature-flagged).")
|
||||
(name = "grin_relay", description = "Grin slatepack relay: async non-custodial mailbox for interactive Grin transfers (feature-flagged)."),
|
||||
(name = "premium", description = "Premium subscription: mint a tier invoice, activate on settlement, read status (feature-flagged).")
|
||||
)
|
||||
)]
|
||||
pub struct ApiDoc;
|
||||
|
||||
Reference in New Issue
Block a user