max / makenotwork
- Co-Authored-By
- Claude Opus 4.6 (1M context) <noreply@anthropic.com>
13 files changed,
+337 insertions,
-40 deletions
| @@ -3385,7 +3385,7 @@ | |||
| 3385 | 3385 | ||
| 3386 | 3386 | [[package]] | |
| 3387 | 3387 | name = "makenotwork" | |
| 3388 | - | version = "0.4.0" | |
| 3388 | + | version = "0.4.2" | |
| 3389 | 3389 | dependencies = [ | |
| 3390 | 3390 | "anyhow", | |
| 3391 | 3391 | "argon2", |
| @@ -6,6 +6,25 @@ | |||
| 6 | 6 | ||
| 7 | 7 | --- | |
| 8 | 8 | ||
| 9 | + | ## Code Fuzz Findings (2026-04-26) | |
| 10 | + | ||
| 11 | + | ### Critical | |
| 12 | + | - [ ] Cross-community post removal via flag: `remove_flagged_post_handler` and `dismiss_flag_handler` verify mod/owner of the URL slug community but act on any `flag_id` without checking it belongs to that community. A mod of community-A can remove posts from community-B. Fix: after fetching the flag row, join through posts→threads→categories to get community_id and verify it matches. (`src/routes/flagging.rs:101,128`) | |
| 13 | + | ||
| 14 | + | ### Serious | |
| 15 | + | - [ ] Cross-community category edit: `edit_category_handler` verifies owner of slug community, then updates any category by UUID. Fix: add `AND community_id = $2` to the UPDATE in `update_category`. (`src/routes/settings.rs:231`, `crates/mt-db/src/mutations.rs:349`) | |
| 16 | + | - [ ] Cross-community tag delete: `delete_tag_handler` verifies owner of slug community, then deletes any tag by UUID. Fix: add `AND community_id = $2` to the DELETE in `delete_tag`. (`src/routes/settings.rs:363`, `crates/mt-db/src/mutations.rs:666`) | |
| 17 | + | - [ ] Search query panics on multi-byte UTF-8: `&q[..200]` panics if byte 200 is mid-character. Fix: use `is_char_boundary` loop to find a safe truncation point. (`src/routes/search.rs:32`) | |
| 18 | + | - [ ] SSRF bypass in link preview via alternative IP encodings (octal, decimal, hex, shorthand, IPv6-mapped IPv4). String-based host check doesn't catch them. Fix: parse host with `std::net::IpAddr` to normalize all IP representations before checking private ranges. (`src/link_preview.rs:13`) | |
| 19 | + | ||
| 20 | + | ### Minor | |
| 21 | + | - [ ] `parse_duration` silently defaults unknown strings to permanent ban (e.g. typo "3d" → permanent). Fix: return error on unrecognized values. (`src/routes/helpers.rs:275`) | |
| 22 | + | - [ ] `/internal/threads/{id}/stats` is unauthenticated and publicly accessible (thread UUIDs visible in URLs). Fix: add `InternalAuth` extractor or accept the info leak. (`src/routes/internal.rs:276`) | |
| 23 | + | - [ ] `auto_hide_if_threshold_met` records the flagger's user_id as `removed_by`, not a system/mod account. Misleading audit trail. (`src/routes/flagging.rs:82`) | |
| 24 | + | - [ ] `/search` endpoint has no rate limiting (GET in read_routes). Full-text + trigram similarity queries are expensive. Fix: add per-IP rate limit or move to write_routes group. (`src/routes/search.rs`) | |
| 25 | + | ||
| 26 | + | --- | |
| 27 | + | ||
| 9 | 28 | ## Code Review Remediation — Remaining | |
| 10 | 29 | - [ ] Transitive dep advisories: rand 0.8/0.9 (RUSTSEC-2026-0097), rsa (RUSTSEC-2023-0071), lru (RUSTSEC-2026-0002) — no direct fix available, monitor upstream | |
| 11 | 30 | - [ ] Add partial index on `posts.removed_at` (`WHERE removed_at IS NOT NULL`) when data volume warrants it |
| @@ -120,7 +120,7 @@ | |||
| 120 | 120 | ||
| 121 | 121 | ## Code Fuzz Findings (2026-04-25) | |
| 122 | 122 | ||
| 123 | - | Two rounds of adversarial code review. 31 findings total: 30 fixed, 1 accepted risk, 1 deferred. | |
| 123 | + | Three rounds of adversarial code review. 51 findings total: 50 fixed, 1 accepted risk, 1 deferred. | |
| 124 | 124 | ||
| 125 | 125 | ### Accepted Risk | |
| 126 | 126 | - Idempotency check not atomic with operation — concurrent requests both execute (`db/idempotency.rs`). Safe because underlying ops are themselves idempotent. | |
| @@ -131,6 +131,46 @@ | |||
| 131 | 131 | ### Resolved (28 findings) | |
| 132 | 132 | All critical, serious, and minor findings from rounds 1 and 2 are fixed. See git history for details. | |
| 133 | 133 | ||
| 134 | + | ## Code Fuzz Findings -- Round 3 (2026-04-25) | |
| 135 | + | ||
| 136 | + | ### Fixed | |
| 137 | + | - [x] SubscriptionStatus missing Trialing/Incomplete/IncompleteExpired variants (db/enums.rs) | |
| 138 | + | - [x] SyncKit auth does not block deactivated users (synckit_auth.rs) | |
| 139 | + | - [x] Build token comparison not constant-time (routes/builds.rs) | |
| 140 | + | - [x] Subscription access checks ignore paused_at (db/subscriptions.rs) | |
| 141 | + | - [x] Cover/MediaImage uploads bypass storage cap with i64::MAX (db/creator_tiers.rs) | |
| 142 | + | - [x] Promo code use_count consumed even when user already owns item (db/transactions.rs) | |
| 143 | + | - [x] Idempotency middleware caches empty string instead of real body (metrics.rs) | |
| 144 | + | - [x] OAuth: no dummy hash on user-not-found path (timing leak, routes/oauth.rs) | |
| 145 | + | - [x] OAuth: no password length cap (Argon2 DoS, routes/oauth.rs) | |
| 146 | + | - [x] OAuth: suspended/deactivated users can still authorize (routes/oauth.rs) | |
| 147 | + | - [x] OAuth session validation: result.valid not checked before suspension (routes/oauth.rs) | |
| 148 | + | - [x] OAuth legacy session path ignores deactivated flag (routes/oauth.rs) | |
| 149 | + | - [x] Subscription test fixture missing paused_at field (db/models/subscription.rs) | |
| 150 | + | - [x] Git routes have no rate limiting (routes/git/mod.rs) | |
| 151 | + | - [x] No Content-Security-Policy header (lib.rs) | |
| 152 | + | - [x] /metrics endpoint unprotected (lib.rs) | |
| 153 | + | - [x] Upload confirm: no idempotency, no S3 cleanup on storage error (routes/storage/uploads.rs) | |
| 154 | + | - [x] Version confirm: no idempotency, no S3 cleanup on storage error (routes/storage/versions.rs) | |
| 155 | + | - [x] Image confirm: storage increment after DB write, no idempotency (routes/storage/images.rs) | |
| 156 | + | - [x] Media confirm: no content_type/extension re-validation, no S3 cleanup (routes/storage/media.rs) | |
| 157 | + | ||
| 158 | + | - [x] CSRF token not rotated after login -- now regenerated in login_user (auth.rs, csrf.rs) | |
| 159 | + | - [x] Read-modify-write race on sort_order/position -- atomic INSERT...SELECT (db/custom_links.rs, db/collections.rs) | |
| 160 | + | - [x] N+1 reorder loops without transactions -- wrapped in transactions (db/custom_links.rs, db/collections.rs) | |
| 161 | + | - [x] Race condition in custom domain creation -- SELECT FOR UPDATE in transaction (db/custom_domains.rs) | |
| 162 | + | ||
| 163 | + | - [x] Double-purchase TOCTOU -- partial unique index on (buyer_id, item_id/project_id) WHERE status='pending' prevents concurrent checkouts (migration 073, checkout handlers) | |
| 164 | + | ||
| 165 | + | - [x] Promo code max_uses bypassable on paid path -- use_count now reserved at checkout time, released by scheduler on stale cleanup (migration 074, checkout handlers, scheduler) | |
| 166 | + | ||
| 167 | + | ### Deferred | |
| 168 | + | - Rate limit IP extraction trusts X-Forwarded-For when traffic bypasses Cloudflare (helpers.rs). Fix requires splitting rate limit extraction by path: CF-Connecting-IP for public web routes, peer socket for internal/CLI/git. Needs careful routing since CLI, git smart HTTP, and SyncKit all hit the same server but some bypass Cloudflare. | |
| 169 | + | - S3 key/file size UPDATE queries lack ownership in SQL -- defense-in-depth; callers verify ownership (db/items.rs) | |
| 170 | + | ||
| 171 | + | ### Accepted | |
| 172 | + | - Revoked session usable for up to 30s -- session cache IS cleared by revoke_session and revoke_other_sessions handlers; window only applies to direct DB manipulation (admin) | |
| 173 | + | ||
| 134 | 174 | --- | |
| 135 | 175 | ||
| 136 | 176 | ## Creator Trust Audit (2026-04-25) | |
| @@ -140,8 +180,24 @@ | |||
| 140 | 180 | ### Resolved (20+ findings) | |
| 141 | 181 | All doc/code fixes, trust gaps, security issues, and doc clarity items are complete. Key changes: subscription export endpoint, offsite backups with WAM alerting, API key hashing, security headers, fan subscription pause on suspension, account limbo state, support ticket portal, expanded tax/payout/discovery/storage docs, privacy policy updates. See git history. | |
| 142 | 182 | ||
| 143 | - | ### Remaining | |
| 144 | - | - [ ] No incident post-mortems or public historical incident log (process, not code) | |
| 183 | + | ### Doc/Code Contradictions (all resolved) | |
| 184 | + | - [x] Payout minimum: aligned payouts.md with Stripe reality ($1 minimum), named Stripe explicitly | |
| 185 | + | - [x] Content protection watermarking: scoped claim to "audio and image files delivered without watermarks", disclosed text fingerprinting | |
| 186 | + | - [x] Mailing list import: reworded as roadmap item, linked to migration guide | |
| 187 | + | - [x] IP retention: added daily scheduler job scrubbing IPs from user_sessions, download_fingerprints, streaming_sessions at 30 days | |
| 188 | + | ||
| 189 | + | ### Missing Creator-Facing Documentation | |
| 190 | + | - [x] Named Stripe explicitly in payouts.md and payments.md (replaced all "payment processor" references) | |
| 191 | + | - [x] Creator application criteria added to getting-started.md (what we look for, what gets rejected) | |
| 192 | + | - [x] Tips documented (new guide/tips.md) | |
| 193 | + | - [x] Bundles documented (new guide/bundles.md) | |
| 194 | + | - [x] Revenue splits documented (new guide/splits.md) | |
| 195 | + | - [x] Currencies/countries: linked to Stripe's own docs (46+ countries, 135+ currencies) rather than maintaining stale tables; fixed grammar from bulk find-replace | |
| 196 | + | ||
| 197 | + | ### Trust Gaps | |
| 198 | + | - [x] 30-day post-termination export window -- migration 076 adds terminated_at; admin terminate route (requires prior suspension); scheduler deletes after 30 days; Stripe subscriptions canceled; termination email sent with export instructions | |
| 199 | + | - [x] Per-item content removal admin action -- migration 075, admin routes (remove/restore), email notifications, publish guards prevent re-publishing removed items | |
| 200 | + | - ~~No incident post-mortems or public historical incident log~~ — will publish as posts in the MNW Changelog blog project | |
| 145 | 201 | ||
| 146 | 202 | ### Competitive Positioning (acknowledged, not bugs) | |
| 147 | 203 | - No free tier — deliberate tradeoff. Earn-back credit program planned. |
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | 3 | Your first 15 minutes on Makenot.work — from sign-up to your first published item. | |
| 4 | 4 | ||
| 5 | + | **Not ready to commit?** [Try sandbox mode](./sandbox.md) to explore the full creator dashboard without signing up. It lasts 1 hour and requires no account. | |
| 6 | + | ||
| 5 | 7 | ## Create Your Account | |
| 6 | 8 | ||
| 7 | 9 | 1. Visit the homepage and click **Join** | |
| @@ -26,16 +28,18 @@ | |||
| 26 | 28 | ||
| 27 | 29 | Most applications are approved within a few days. You'll get an email when you're in. | |
| 28 | 30 | ||
| 31 | + | **What we look for:** We approve anyone who makes original creative work -- music, writing, software, art, video, courses. We don't require a minimum audience or existing sales history. Applications are rejected only for content that violates our [acceptable use policy](../legal/acceptable-use.md) (e.g., reselling others' work, prohibited content). | |
| 32 | + | ||
| 29 | 33 | ## Connect Payments | |
| 30 | 34 | ||
| 31 | - | Once approved as a creator, connect your payment account to receive fan payments: | |
| 35 | + | Once approved as a creator, connect Stripe to receive fan payments: | |
| 32 | 36 | ||
| 33 | 37 | 1. Go to your **Dashboard** | |
| 34 | 38 | 2. Click **Connect Payments** | |
| 35 | - | 3. Follow the payment onboarding flow | |
| 36 | - | 4. Complete identity verification (payment processor requirement) | |
| 39 | + | 3. Follow the Stripe onboarding flow | |
| 40 | + | 4. Complete identity verification (Stripe requirement) | |
| 37 | 41 | ||
| 38 | - | Payments go directly to your payment account. We never hold or touch your revenue. | |
| 42 | + | Payments go directly to your Stripe account. We never hold or touch your revenue. | |
| 39 | 43 | ||
| 40 | 44 | ## Create Your First Project | |
| 41 | 45 |
| @@ -53,7 +53,7 @@ | |||
| 53 | 53 | ||
| 54 | 54 | ## Importing Subscribers | |
| 55 | 55 | ||
| 56 | - | You can import external email addresses (people without Makenot.work accounts) to your mailing lists. This is useful when migrating from another platform. | |
| 56 | + | Subscriber import from other platforms (CSV upload with consent emails) is on the roadmap but not yet available. When migrating, use the [data import tools](./migration.md) to bring over your content; your audience can follow your new project to subscribe. | |
| 57 | 57 | ||
| 58 | 58 | ## See Also | |
| 59 | 59 |
| @@ -4,14 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | 5 | We use a direct-deposit payment model. When you sign up: | |
| 6 | 6 | ||
| 7 | - | 1. Connect or create a payment account | |
| 8 | - | 2. Verify your identity (payment processor requirement) | |
| 7 | + | 1. Connect or create a Stripe account | |
| 8 | + | 2. Verify your identity (Stripe requirement) | |
| 9 | 9 | 3. Link your bank account | |
| 10 | 10 | 4. Payments flow directly to you | |
| 11 | 11 | ||
| 12 | 12 | ## Payout Schedule | |
| 13 | 13 | ||
| 14 | - | You control this in your payment processor's dashboard: | |
| 14 | + | You control this in your [Stripe dashboard](https://dashboard.stripe.com): | |
| 15 | 15 | ||
| 16 | 16 | - **Instant**: Available immediately (small fee) | |
| 17 | 17 | - **Daily**: Next business day | |
| @@ -22,11 +22,11 @@ | |||
| 22 | 22 | ||
| 23 | 23 | ## Minimum Payout | |
| 24 | 24 | ||
| 25 | - | No minimum. Even $0.01 will transfer (though processing fees make tiny amounts impractical). | |
| 25 | + | Stripe requires a minimum balance before payout (typically $1). You can set a higher threshold if you prefer larger, less frequent payouts. Processing fees make very small amounts impractical regardless of the minimum. | |
| 26 | 26 | ||
| 27 | 27 | ## International Creators | |
| 28 | 28 | ||
| 29 | - | Our payment processor supports 40+ countries. Payouts are converted to your local currency by the payment processor when your country's currency differs from the purchase currency (USD). Conversion rates and any currency conversion fees are set by the payment processor, not by us. | |
| 29 | + | Stripe supports creators in [46+ countries](https://stripe.com/global). Payouts are converted to your local currency by Stripe when your country's currency differs from the purchase currency (USD). Conversion rates and any currency conversion fees are set by Stripe, not by us. | |
| 30 | 30 | ||
| 31 | 31 | If your country isn't supported, contact us — we're working on alternatives. | |
| 32 | 32 | ||
| @@ -36,19 +36,19 @@ | |||
| 36 | 36 | ||
| 37 | 37 | ### US Creators | |
| 38 | 38 | ||
| 39 | - | - The payment processor issues a **1099-K** if your gross payments exceed IRS reporting thresholds ($600/year as of 2024) | |
| 39 | + | - Stripe issues a **1099-K** if your gross payments exceed IRS [reporting thresholds](https://support.stripe.com/topics/1099-tax-forms) ($600/year as of 2024) | |
| 40 | 40 | - You are responsible for reporting all income, including amounts below the 1099-K threshold | |
| 41 | - | - We do not issue 1099-MISC or W-2 forms — your relationship is with the payment processor, not with us as an employer | |
| 41 | + | - We do not issue 1099-MISC or W-2 forms — your relationship is with Stripe, not with us as an employer | |
| 42 | 42 | - Keep your own records: your dashboard shows revenue charts and full transaction history, and you can export sales as CSV at any time | |
| 43 | 43 | - Consult a tax professional if you are unsure about your obligations — this is not tax advice | |
| 44 | 44 | ||
| 45 | 45 | ### Non-US Creators | |
| 46 | 46 | ||
| 47 | 47 | - Follow your local tax laws for self-employment or platform income | |
| 48 | - | - The payment processor provides transaction records and may issue tax forms required by your jurisdiction | |
| 48 | + | - Stripe provides transaction records and may issue tax forms required by your jurisdiction | |
| 49 | 49 | - VAT/GST collection is your responsibility — we do not currently collect or remit taxes on your behalf | |
| 50 | 50 | - We provide annual revenue summaries on request (email billing@makenot.work) | |
| 51 | - | - If your country requires tax withholding on cross-border payments, the payment processor handles this based on your W-8BEN or equivalent tax form | |
| 51 | + | - If your country requires tax withholding on cross-border payments, Stripe handles this based on your W-8BEN or equivalent tax form | |
| 52 | 52 | ||
| 53 | 53 | <!-- PENDING: This section should be reviewed by a tax professional. --> | |
| 54 | 54 | <!-- Specific areas: 1099-K threshold accuracy, international withholding guidance, VAT/GST obligations. --> | |
| @@ -62,15 +62,15 @@ | |||
| 62 | 62 | - Per-project and per-item breakdowns | |
| 63 | 63 | - Full transaction history | |
| 64 | 64 | ||
| 65 | - | Your payment processor's dashboard provides additional payout detail (pending transfers, completed payouts, payout schedule). | |
| 65 | + | Your [Stripe dashboard](https://dashboard.stripe.com) provides additional payout detail (pending transfers, completed payouts, payout schedule). | |
| 66 | 66 | ||
| 67 | 67 | ## Refunds | |
| 68 | 68 | ||
| 69 | 69 | If a fan requests a refund and you approve: | |
| 70 | 70 | ||
| 71 | 71 | - Funds deducted from your next payout | |
| 72 | - | - Or from your payment account balance | |
| 73 | - | - Refund fees may apply (payment processor policy) | |
| 72 | + | - Or from your Stripe balance | |
| 73 | + | - Refund fees may apply ([Stripe refund policy](https://docs.stripe.com/refunds)) | |
| 74 | 74 | ||
| 75 | 75 | You have full control over refund decisions. | |
| 76 | 76 | ||
| @@ -78,3 +78,5 @@ | |||
| 78 | 78 | ||
| 79 | 79 | - [Analytics & Dashboard](./analytics.md) — Revenue charts and transaction history | |
| 80 | 80 | - [Pricing & Monetization](./03-selling.md) — Setting prices and payment flow | |
| 81 | + | - [Stripe Global](https://stripe.com/global) — Supported countries | |
| 82 | + | - [Stripe Payouts](https://docs.stripe.com/payouts) — Payout schedules and timing |
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | 7 | ## The Short Version | |
| 8 | 8 | ||
| 9 | - | Our payment processor handles all payments. You're the merchant of record. We don't take a cut of your revenue. Fans handle refunds with you or dispute via their bank. | |
| 9 | + | Stripe handles all payments. You're the merchant of record. We don't take a cut of your revenue. Fans handle refunds with you or dispute via their bank. | |
| 10 | 10 | ||
| 11 | 11 | --- | |
| 12 | 12 | ||
| @@ -16,8 +16,8 @@ | |||
| 16 | 16 | ||
| 17 | 17 | When fans buy your content or subscribe: | |
| 18 | 18 | ||
| 19 | - | 1. Fan pays via payment processor (~2.9% + $0.30 per transaction) | |
| 20 | - | 2. Funds go directly to your connected payment account | |
| 19 | + | 1. Fan pays via Stripe (~2.9% + $0.30 per transaction) | |
| 20 | + | 2. Funds go directly to your connected Stripe account | |
| 21 | 21 | 3. Deposits to your bank on your chosen schedule | |
| 22 | 22 | 4. We never touch or hold your money | |
| 23 | 23 | ||
| @@ -33,12 +33,12 @@ | |||
| 33 | 33 | ||
| 34 | 34 | ## You're the Merchant of Record | |
| 35 | 35 | ||
| 36 | - | When you connect payments, the processor creates an account for you. This means: | |
| 36 | + | When you connect Stripe, it creates an account for you. This means: | |
| 37 | 37 | ||
| 38 | 38 | - **You are the merchant** - Fans are paying you, not us | |
| 39 | 39 | - **You set prices** - Including pay-what-you-want options | |
| 40 | 40 | - **You handle disputes** - Chargebacks and refunds are your responsibility | |
| 41 | - | - **Your payment account is yours** - If you leave, it stays with you | |
| 41 | + | - **Your Stripe account is yours** - If you leave, it stays with you | |
| 42 | 42 | ||
| 43 | 43 | This keeps your revenue in your hands. The tradeoff: you absorb the (typically rare) chargeback risk. | |
| 44 | 44 | ||
| @@ -46,7 +46,7 @@ | |||
| 46 | 46 | ||
| 47 | 47 | ## Payouts | |
| 48 | 48 | ||
| 49 | - | You control when funds move from your payment account balance to your bank: | |
| 49 | + | You control when funds move from your Stripe balance to your bank: | |
| 50 | 50 | ||
| 51 | 51 | | Schedule | Timing | Notes | | |
| 52 | 52 | |----------|--------|-------| | |
| @@ -75,7 +75,7 @@ | |||
| 75 | 75 | ||
| 76 | 76 | Fans should contact you directly. You can: | |
| 77 | 77 | ||
| 78 | - | - Issue a full or partial refund via your payment processor's dashboard | |
| 78 | + | - Issue a full or partial refund via your [Stripe dashboard](https://dashboard.stripe.com) | |
| 79 | 79 | - Offer alternative resolution (access fix, different content) | |
| 80 | 80 | - Decline if the purchase was delivered as promised | |
| 81 | 81 | ||
| @@ -96,7 +96,7 @@ | |||
| 96 | 96 | If a fan disputes a charge with their bank: | |
| 97 | 97 | ||
| 98 | 98 | 1. **Your balance is debited** - Disputed amount plus fee (~$15) | |
| 99 | - | 2. **You respond through the payment processor** - Provide evidence the charge was legitimate | |
| 99 | + | 2. **You respond through Stripe** - Provide evidence the charge was legitimate | |
| 100 | 100 | 3. **Bank decides** - You either get the money back or lose it | |
| 101 | 101 | ||
| 102 | 102 | ### Why This Model | |
| @@ -134,7 +134,7 @@ | |||
| 134 | 134 | ### What We Provide | |
| 135 | 135 | ||
| 136 | 136 | - **Transaction records** - Exportable history of all payments | |
| 137 | - | - **1099-K** (US creators) - Issued by the payment processor if you meet thresholds | |
| 137 | + | - **1099-K** (US creators) - Issued by Stripe if you meet [reporting thresholds](https://support.stripe.com/topics/1099-tax-forms) | |
| 138 | 138 | - **Invoices** - For your platform subscription | |
| 139 | 139 | ||
| 140 | 140 | ### Your Responsibilities | |
| @@ -153,22 +153,22 @@ | |||
| 153 | 153 | ||
| 154 | 154 | ## International Payments | |
| 155 | 155 | ||
| 156 | - | Our payment processor supports 40+ countries. Creators outside the US: | |
| 156 | + | Stripe supports creators in [46+ countries](https://stripe.com/global). Creators outside the US: | |
| 157 | 157 | ||
| 158 | - | - Set up a payment account in your country | |
| 159 | - | - Receive payments in multiple currencies | |
| 160 | - | - The payment processor handles currency conversion | |
| 158 | + | - Set up a Stripe account in your country | |
| 159 | + | - Receive payments in [135+ currencies](https://docs.stripe.com/currencies) | |
| 160 | + | - Stripe handles currency conversion automatically | |
| 161 | 161 | ||
| 162 | - | Conversion rates and timing vary by country. Check your payment processor's documentation for specifics. | |
| 162 | + | Conversion rates and timing vary by country. See [Stripe's payout documentation](https://docs.stripe.com/payouts) for specifics. | |
| 163 | 163 | ||
| 164 | 164 | --- | |
| 165 | 165 | ||
| 166 | 166 | ## What We Don't Do | |
| 167 | 167 | ||
| 168 | - | - **Hold creator funds** - Money goes directly to your payment account | |
| 168 | + | - **Hold creator funds** - Money goes directly to your Stripe account | |
| 169 | 169 | - **Take a percentage** - Our fee is flat monthly subscription only | |
| 170 | 170 | - **Control your pricing** - Set whatever prices you want | |
| 171 | - | - **Process payments ourselves** - Our payment processor handles everything | |
| 171 | + | - **Process payments ourselves** - Stripe handles everything | |
| 172 | 172 | - **Provide tax advice** - Consult a professional | |
| 173 | 173 | ||
| 174 | 174 | --- | |
| @@ -177,4 +177,6 @@ | |||
| 177 | 177 | ||
| 178 | 178 | - [Creator Guarantees](../about/guarantees.md) - our commitments on revenue | |
| 179 | 179 | - [Pricing Tiers](../guide/tiers.md) - tier features and pricing | |
| 180 | - | - [Infrastructure & Vendors](../tech/infrastructure.md) - current payment processor details | |
| 180 | + | - [Stripe Global](https://stripe.com/global) - supported countries | |
| 181 | + | - [Stripe Currencies](https://docs.stripe.com/currencies) - supported currencies | |
| 182 | + | - [Stripe Connect](https://stripe.com/connect) - how the payment model works |
| @@ -12,7 +12,9 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ## What We Do Instead | |
| 14 | 14 | ||
| 15 | - | We give fans clean, unencumbered files. Presigned download URLs are time-limited and tied to authenticated accounts, so casual link-sharing doesn't work. But we don't embed watermarks, restrict playback, or limit how fans use files they've paid for. | |
| 15 | + | We give fans clean, unencumbered files. Presigned download URLs are time-limited and tied to authenticated accounts, so casual link-sharing doesn't work. We don't restrict playback or limit how fans use files they've paid for. | |
| 16 | + | ||
| 17 | + | For text files (README, LICENSE, liner notes), we may embed an invisible fingerprint tied to the buyer's purchase. This lets creators trace leaked files back to a specific download without affecting the content's usability. Audio and image files are delivered without watermarks. | |
| 16 | 18 | ||
| 17 | 19 | If you need stronger protection than this, we may not be the right platform for your content. We'd rather be honest about that upfront. | |
| 18 | 20 |