Skip to main content

max / makenotwork

Email infrastructure, bounce handling, UX improvements, and pre-deploy fixes - Postmark bounce/complaint webhook with email suppression table - Email unsubscribe system: signed URLs, List-Unsubscribe headers (RFC 8058), one-click POST handler, per-notification opt-out - Release announcement opt-in (notify_release preference, filtered follower query) - Login notification toggle on preferences form - Creator-only notification prefs (sale/follower hidden for non-creators) - Broadcast confirmation with follower count - Password form clears on successful change - Copy button shows "Copied!" feedback - Email verification nudge on Account tab - SyncKit blob storage, app linking, device management - Discount code project scoping, Stripe webhook v2 support - Stripe Connect flow refactor (oauth.rs → connect.rs) - Admin CLI tool (mnw-admin) - Fix promotions tab test (tab removed, test updated) - Doc updates (roadmap, FAQ, terms, infrastructure) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-03-09 00:17 UTC
Commit: cba62a077006126961ad7534bf1cd280a0236641
Parent: 8b4f346
98 files changed, +3476 insertions, -749 deletions
@@ -12,9 +12,8 @@
12 12 SESSION_SECRET=your-session-secret-change-in-production
13 13
14 14 # Optional: Stripe Connect (payments)
15 - # Get these from https://dashboard.stripe.com/settings/connect
15 + # Get these from https://dashboard.stripe.com/apikeys
16 16 # STRIPE_SECRET_KEY=sk_test_...
17 - # STRIPE_CLIENT_ID=ca_...
18 17 # STRIPE_WEBHOOK_SECRET=whsec_...
19 18 # HOST_URL=http://localhost:3000
20 19
@@ -77,12 +77,56 @@
77 77 "unicode-width",
78 78 ]
79 79
80 + [[package]]
81 + name = "anstream"
82 + version = "0.6.21"
83 + source = "registry+https://github.com/rust-lang/crates.io-index"
84 + checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
85 + dependencies = [
86 + "anstyle",
87 + "anstyle-parse",
88 + "anstyle-query",
89 + "anstyle-wincon",
90 + "colorchoice",
91 + "is_terminal_polyfill",
92 + "utf8parse",
93 + ]
94 +
80 95 [[package]]
81 96 name = "anstyle"
82 97 version = "1.0.13"
83 98 source = "registry+https://github.com/rust-lang/crates.io-index"
84 99 checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
85 100
101 + [[package]]
102 + name = "anstyle-parse"
103 + version = "0.2.7"
104 + source = "registry+https://github.com/rust-lang/crates.io-index"
105 + checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
106 + dependencies = [
107 + "utf8parse",
108 + ]
109 +
110 + [[package]]
111 + name = "anstyle-query"
112 + version = "1.1.5"
113 + source = "registry+https://github.com/rust-lang/crates.io-index"
114 + checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
115 + dependencies = [
116 + "windows-sys 0.61.2",
117 + ]
118 +
119 + [[package]]
120 + name = "anstyle-wincon"
121 + version = "3.0.11"
122 + source = "registry+https://github.com/rust-lang/crates.io-index"
123 + checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
124 + dependencies = [
125 + "anstyle",
126 + "once_cell_polyfill",
127 + "windows-sys 0.61.2",
128 + ]
129 +
86 130 [[package]]
87 131 name = "anyhow"
88 132 version = "1.0.101"
@@ -1189,6 +1233,46 @@
1189 1233 "inout",
1190 1234 ]
1191 1235
1236 + [[package]]
1237 + name = "clap"
1238 + version = "4.5.60"
1239 + source = "registry+https://github.com/rust-lang/crates.io-index"
1240 + checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
1241 + dependencies = [
1242 + "clap_builder",
1243 + "clap_derive",
1244 + ]
1245 +
1246 + [[package]]
1247 + name = "clap_builder"
1248 + version = "4.5.60"
1249 + source = "registry+https://github.com/rust-lang/crates.io-index"
1250 + checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
1251 + dependencies = [
1252 + "anstream",
1253 + "anstyle",
1254 + "clap_lex",
1255 + "strsim",
1256 + ]
1257 +
1258 + [[package]]
1259 + name = "clap_derive"
1260 + version = "4.5.55"
1261 + source = "registry+https://github.com/rust-lang/crates.io-index"
1262 + checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
1263 + dependencies = [
1264 + "heck",
1265 + "proc-macro2",
1266 + "quote",
1267 + "syn 2.0.114",
1268 + ]
1269 +
1270 + [[package]]
1271 + name = "clap_lex"
1272 + version = "1.0.0"
1273 + source = "registry+https://github.com/rust-lang/crates.io-index"
1274 + checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
1275 +
1192 1276 [[package]]
1193 1277 name = "cmake"
1194 1278 version = "0.1.57"
@@ -1207,6 +1291,12 @@
1207 1291 "thiserror 2.0.18",
1208 1292 ]
1209 1293
1294 + [[package]]
1295 + name = "colorchoice"
1296 + version = "1.0.4"
1297 + source = "registry+https://github.com/rust-lang/crates.io-index"
1298 + checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
1299 +
1210 1300 [[package]]
1211 1301 name = "concurrent-queue"
1212 1302 version = "2.5.0"
@@ -3062,6 +3152,12 @@
3062 3152 "serde",
3063 3153 ]
3064 3154
3155 + [[package]]
3156 + name = "is_terminal_polyfill"
3157 + version = "1.70.2"
3158 + source = "registry+https://github.com/rust-lang/crates.io-index"
3159 + checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
3160 +
3065 3161 [[package]]
3066 3162 name = "itertools"
3067 3163 version = "0.14.0"
@@ -3357,7 +3453,7 @@
3357 3453
3358 3454 [[package]]
3359 3455 name = "makenotwork"
3360 - version = "0.1.0"
3456 + version = "0.1.4"
3361 3457 dependencies = [
3362 3458 "ammonia",
3363 3459 "anyhow",
@@ -3371,6 +3467,7 @@
3371 3467 "axum-extra",
3372 3468 "base64 0.22.1",
3373 3469 "chrono",
3470 + "clap",
3374 3471 "dotenvy",
3375 3472 "git2",
3376 3473 "goblin",
@@ -3900,6 +3997,12 @@
3900 3997 source = "registry+https://github.com/rust-lang/crates.io-index"
3901 3998 checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
3902 3999
4000 + [[package]]
4001 + name = "once_cell_polyfill"
4002 + version = "1.70.2"
4003 + source = "registry+https://github.com/rust-lang/crates.io-index"
4004 + checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
4005 +
3903 4006 [[package]]
3904 4007 name = "openssl"
3905 4008 version = "0.10.75"
@@ -6525,6 +6628,12 @@
6525 6628 source = "registry+https://github.com/rust-lang/crates.io-index"
6526 6629 checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
6527 6630
6631 + [[package]]
6632 + name = "utf8parse"
6633 + version = "0.2.2"
6634 + source = "registry+https://github.com/rust-lang/crates.io-index"
6635 + checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
6636 +
6528 6637 [[package]]
6529 6638 name = "uuid"
6530 6639 version = "0.8.2"
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makenotwork"
3 - version = "0.1.0"
3 + version = "0.1.4"
4 4 edition = "2024"
5 5 license-file = "../../LICENSE"
6 6
@@ -65,6 +65,9 @@
65 65 zip = "8.2"
66 66 yara-x = "1.13"
67 67
68 + # CLI
69 + clap = { version = "4", features = ["derive"] }
70 +
68 71 # Error handling
69 72 thiserror = "2.0.18"
70 73 anyhow = "1.0.101"
@@ -93,6 +96,10 @@
93 96 # Error tracking
94 97 sentry = { version = "0.38", default-features = false, features = ["backtrace", "contexts", "panic", "tracing", "reqwest", "rustls"] }
95 98
99 + [[bin]]
100 + name = "mnw-admin"
101 + path = "src/bin/mnw-admin.rs"
102 +
96 103 [dev-dependencies]
97 104 tower = { version = "0.5.3", features = ["util"] }
98 105 http-body-util = "0.1"
@@ -6,7 +6,7 @@
6 6
7 7 ## Revenue
8 8
9 - **Guarantee:** 100% of fan payments reach the creator, minus only the payment processor's fee (currently Stripe, ~3%).
9 + **Guarantee:** 0% platform fee on fan payments. The only deduction is the payment processor's fee (currently Stripe, ~3%).
10 10
11 11 - No platform percentage cut, ever.
12 12 - No transaction fees, payout fees, or skimming.