max / makenotwork
121 files changed,
+4907 insertions,
-489 deletions
| @@ -1,7 +1,7 @@ | |||
| 1 | 1 | # mnw-cli TODO | |
| 2 | 2 | ||
| 3 | 3 | ## Status | |
| 4 | - | Done: Phases 1-8, Git proxy A-D (except D5), UX audit fixes (8/8). Active: None. Next: D5 DNS, PoM health check, deploy. | |
| 4 | + | Done: Phases 1-8, Git proxy A-D (incl D5 DNS), UX audit fixes (8/8). Deployed 2026-05-03. Active: None. Next: PoM health check, astra test. | |
| 5 | 5 | ||
| 6 | 6 | --- | |
| 7 | 7 | ||
| @@ -26,7 +26,7 @@ Priority order (highest impact first): | |||
| 26 | 26 | - [x] D2: Update mnw-cli .env (`SSH_PORT=22`, `GIT_SUDO_USER=git`) — done 2026-04-22 | |
| 27 | 27 | - [x] D3: Sudoers rule (`/etc/sudoers.d/mnw-cli-git` — git-upload-pack, git-receive-pack, git-upload-archive, git, tee, chmod) — done 2026-04-22, extended 2026-05-03 | |
| 28 | 28 | - [x] D4: Firewall — removed 2222/tcp, added 2200/tcp — done 2026-04-22 | |
| 29 | - | - [ ] D5: DNS — `cli.makenot.work` A record -> `5.78.144.244`, proxy OFF (needs Cloudflare dashboard) | |
| 29 | + | - [x] D5: DNS — `cli.makenot.work` A record -> `5.78.144.244`, proxy OFF — done 2026-05-03 | |
| 30 | 30 | - [x] D6: Restart sequence verified — admin SSH on 2200, mnw-cli on 22, both running — done 2026-04-22 | |
| 31 | 31 | ||
| 32 | 32 | ## Deploy |
| @@ -0,0 +1,104 @@ | |||
| 1 | + | # Community Moderation Policy | |
| 2 | + | ||
| 3 | + | Internal policy document. Public-facing version TBD. | |
| 4 | + | ||
| 5 | + | ## Principle | |
| 6 | + | ||
| 7 | + | MNW communities are creator-moderated. MNW is not the content police. But MNW does enforce a quality floor: communities that are not maintained will be addressed, because neglected spaces harm fans and reflect on the platform. | |
| 8 | + | ||
| 9 | + | The goal is always to give the creator a real path forward, not to punish. | |
| 10 | + | ||
| 11 | + | ## Fan+ Feature Gating | |
| 12 | + | ||
| 13 | + | Storage-heavy forum features are gated behind Fan+ ($8/mo): | |
| 14 | + | - Signatures (text + image) | |
| 15 | + | - Custom / larger profile images | |
| 16 | + | - Image and video embeds in posts | |
| 17 | + | - Access to private communities | |
| 18 | + | - The + badge (Fan+ exclusive — creators do not get this) | |
| 19 | + | ||
| 20 | + | Creators automatically receive all other Fan+ perks in their own communities at no additional cost (they already pay $10-60/mo for the platform). This keeps rich media behind a paywall, reduces spam and low-effort posting, and ensures the people driving storage costs are contributing revenue. | |
| 21 | + | ||
| 22 | + | Free accounts can: read everything, post text, search, endorse, track threads. | |
| 23 | + | ||
| 24 | + | ## Escalation Ladder | |
| 25 | + | ||
| 26 | + | ### 1. Warning | |
| 27 | + | ||
| 28 | + | Trigger: Unresolved flags older than 14 days, or a sustained pattern of unaddressed reports. | |
| 29 | + | ||
| 30 | + | Action: Private notification to the creator. Factual, not accusatory. "Your community has N unresolved flags. Here's what we're seeing. Please address them within 7 days." | |
| 31 | + | ||
| 32 | + | ### 2. Restricted | |
| 33 | + | ||
| 34 | + | Trigger: No meaningful moderation response after warning period. | |
| 35 | + | ||
| 36 | + | Action: New thread creation disabled for non-moderator accounts. Existing members can still post in existing threads. Creator receives a final notice explaining the restriction and what's needed to lift it. | |
| 37 | + | ||
| 38 | + | ### 3. Frozen | |
| 39 | + | ||
| 40 | + | Trigger: Continued inaction after restriction. | |
| 41 | + | ||
| 42 | + | Action: Community goes read-only. Creator and moderators can still take moderation actions (clear the backlog, ban bad actors, remove posts) to unfreeze. No new content from anyone until the mod queue is addressed. | |
| 43 | + | ||
| 44 | + | ### 4. Clean Slate Offer | |
| 45 | + | ||
| 46 | + | Trigger: Extended freeze with no moderation activity, or a community that has deteriorated beyond reasonable recovery. | |
| 47 | + | ||
| 48 | + | This is the final step before archival. MNW reaches out to the creator directly, privately, one last time. | |
| 49 | + | ||
| 50 | + | The conversation is: | |
| 51 | + | - Factual: here is what we're seeing, here are the numbers | |
| 52 | + | - Not accusatory: could be burnout, life circumstances, overwhelm — the reason doesn't matter | |
| 53 | + | - An offer, not an ultimatum: "We can reset your community to a clean state" | |
| 54 | + | ||
| 55 | + | **If accepted:** | |
| 56 | + | - All threads and posts are cleared | |
| 57 | + | - Community settings, categories, and customizations are preserved | |
| 58 | + | - A brief system notice is posted: "This community was restarted by its creator on [date]." | |
| 59 | + | - Nothing else. No explanation. No blame. No platform statement. | |
| 60 | + | - The creator's account, project, tier, payment history, fan relationships — all untouched | |
| 61 | + | - No moderation action is taken against the creator themselves | |
| 62 | + | - The reset is visible. Members who were active will notice. MNW says nothing further. | |
| 63 | + | ||
| 64 | + | **If declined:** | |
| 65 | + | - Community remains frozen | |
| 66 | + | - Creator can come back and accept the clean slate at any time | |
| 67 | + | - After extended inaction (90+ days frozen), community is archived | |
| 68 | + | - Even archived creators are never punished — but the community stays inactive | |
| 69 | + | ||
| 70 | + | ### 5. Archived | |
| 71 | + | ||
| 72 | + | Trigger: 90+ days frozen with no moderation activity and no clean slate accepted. | |
| 73 | + | ||
| 74 | + | Action: Community is archived. Content preserved but not interactive. Creator can request a clean slate at any point to reactivate. | |
| 75 | + | ||
| 76 | + | ## What MNW Never Does | |
| 77 | + | ||
| 78 | + | - Public announcement about why a community was reset or frozen | |
| 79 | + | - Marking the creator's profile, project page, or storefront | |
| 80 | + | - Discussing the situation with other creators or fans | |
| 81 | + | - Using moderation history as a factor in unrelated account decisions | |
| 82 | + | - Naming or shaming in any context | |
| 83 | + | ||
| 84 | + | ## Monitoring | |
| 85 | + | ||
| 86 | + | PoM should track: | |
| 87 | + | - Unresolved flag age per community (alert when oldest unresolved flag exceeds 14 days) | |
| 88 | + | - Flag-to-moderation-action ratio over a 30-day rolling window | |
| 89 | + | - Communities in restricted/frozen/archived state | |
| 90 | + | ||
| 91 | + | Escalation decisions are always human-reviewed. Automated monitoring identifies candidates; a person decides whether to act. | |
| 92 | + | ||
| 93 | + | ## Implementation Status | |
| 94 | + | ||
| 95 | + | - [x] Community suspension (admin.rs) | |
| 96 | + | - [x] Flag system with auto-hide threshold | |
| 97 | + | - [x] Mod action logging (19 action types) | |
| 98 | + | - [x] Ban/mute with duration support | |
| 99 | + | - [ ] Automated flag age monitoring in PoM | |
| 100 | + | - [ ] Restricted state (disable new thread creation) | |
| 101 | + | - [ ] Frozen state (read-only mode) | |
| 102 | + | - [ ] Clean slate mechanism (clear threads, post system notice, preserve settings) | |
| 103 | + | - [ ] Archived state with reactivation path | |
| 104 | + | - [ ] Public-facing documentation of this policy |
| @@ -19,11 +19,26 @@ v0.3.4. Audit grade A. 228 tests. | |||
| 19 | 19 | - [ ] Crashes (crash reports from DS2) | |
| 20 | 20 | - [ ] Feedback (user feedback from DS3) | |
| 21 | 21 | ||
| 22 | + | ### Fan+ Feature Gating | |
| 23 | + | - [ ] Signatures (text + image, rendered on every post) — Fan+ only | |
| 24 | + | - [ ] Custom / larger profile images — Fan+ only (free accounts get generated avatar) | |
| 25 | + | - [ ] Image and video embeds in posts — Fan+ only (free accounts post text only) | |
| 26 | + | - [ ] Creator auto-grant: creators get all Fan+ forum perks in own communities (no + badge) | |
| 27 | + | - [ ] + badge rendering in post author display | |
| 28 | + | ||
| 22 | 29 | ### Private Communities (Fan+) | |
| 23 | 30 | - [ ] Community visibility flag (public/private) | |
| 24 | 31 | - [ ] Membership gating: restrict join to Fan+ subscribers or item buyers | |
| 25 | 32 | - [ ] Hidden from public listing, accessible only via direct link or MNW project page | |
| 26 | 33 | ||
| 34 | + | ### Community Moderation Enforcement | |
| 35 | + | - [ ] Restricted state: disable new thread creation for non-moderators | |
| 36 | + | - [ ] Frozen state: community goes read-only, mods can still take mod actions to unfreeze | |
| 37 | + | - [ ] Clean slate mechanism: clear all threads/posts, preserve settings/categories, post system notice | |
| 38 | + | - [ ] Archived state with reactivation path | |
| 39 | + | - [ ] PoM integration: flag age monitoring, flag-to-action ratio alerts | |
| 40 | + | - [ ] Document moderation policy publicly (see `docs/internal/moderation_policy.md` for internal version) | |
| 41 | + | ||
| 27 | 42 | ### Notification Integration | |
| 28 | 43 | - [ ] Push mentions, replies, endorsements, flags to MNW notifications API | |
| 29 | 44 | - [ ] Read state synced with MNW notification center |
| @@ -3385,7 +3385,7 @@ dependencies = [ | |||
| 3385 | 3385 | ||
| 3386 | 3386 | [[package]] | |
| 3387 | 3387 | name = "makenotwork" | |
| 3388 | - | version = "0.4.8" | |
| 3388 | + | version = "0.4.9" | |
| 3389 | 3389 | dependencies = [ | |
| 3390 | 3390 | "anyhow", | |
| 3391 | 3391 | "argon2", |
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | [package] | |
| 2 | 2 | name = "makenotwork" | |
| 3 | - | version = "0.4.8" | |
| 3 | + | version = "0.4.9" | |
| 4 | 4 | edition = "2024" | |
| 5 | 5 | license-file = "LICENSE" | |
| 6 | 6 |
| @@ -190,3 +190,35 @@ tail -20 /opt/makenotwork/backups/backup.log | |||
| 190 | 190 | # Check cron is scheduled | |
| 191 | 191 | sudo crontab -u makenotwork -l | |
| 192 | 192 | ``` | |
| 193 | + | ||
| 194 | + | --- | |
| 195 | + | ||
| 196 | + | ## Monthly Restore Test | |
| 197 | + | ||
| 198 | + | Run once per month to verify backups are actually restorable. Use the offsite copy on astra to avoid touching production. | |
| 199 | + | ||
| 200 | + | ```bash | |
| 201 | + | # On astra — restore latest backup to a scratch database | |
| 202 | + | LATEST=$(ls -t /opt/backups/mnw/makenotwork-*.sql.gz | head -1) | |
| 203 | + | sudo -u postgres createdb mnw_restore_test -O postgres | |
| 204 | + | gunzip -c "$LATEST" | psql -U postgres -d mnw_restore_test -q | |
| 205 | + | ||
| 206 | + | # Verify row counts (should be non-zero) | |
| 207 | + | psql -U postgres -d mnw_restore_test -c "SELECT 'users' AS t, COUNT(*) FROM users UNION ALL SELECT 'projects', COUNT(*) FROM projects UNION ALL SELECT 'items', COUNT(*) FROM items UNION ALL SELECT 'transactions', COUNT(*) FROM transactions;" | |
| 208 | + | ||
| 209 | + | # Verify migration state | |
| 210 | + | psql -U postgres -d mnw_restore_test -c "SELECT COUNT(*) AS migrations FROM _sqlx_migrations;" | |
| 211 | + | ||
| 212 | + | # Clean up | |
| 213 | + | sudo -u postgres dropdb mnw_restore_test | |
| 214 | + | ||
| 215 | + | # Log result | |
| 216 | + | echo "$(date -u +%Y-%m-%d) restore-test OK: $LATEST" >> /opt/backups/mnw/restore-test.log | |
| 217 | + | ``` | |
| 218 | + | ||
| 219 | + | If any step fails, investigate immediately — a backup that can't be restored isn't a backup. | |
| 220 | + | ||
| 221 | + | Schedule via cron on astra (first of each month): | |
| 222 | + | ``` | |
| 223 | + | 0 4 1 * * /opt/backups/mnw/test-restore.sh >> /opt/backups/mnw/restore-test.log 2>&1 | |
| 224 | + | ``` |
| @@ -1,31 +1,31 @@ | |||
| 1 | 1 | # MakeNotWork -- Audit Review | |
| 2 | 2 | ||
| 3 | - | **Last audited:** 2026-05-01 (Run 18, MNW server only) | |
| 4 | - | **Previous audit:** 2026-04-30 (Run 17, cross-project) | |
| 3 | + | **Last audited:** 2026-05-02 (Run 19, MNW server + doc fuzz) | |
| 4 | + | **Previous audit:** 2026-05-01 (Run 18, MNW server only) | |
| 5 | 5 | ||
| 6 | 6 | ## Overall Grade: A | |
| 7 | 7 | ||
| 8 | - | Run 18: 1,933 tests (1,209 unit + 724 integration). 0 clippy warnings. v0.4.6. ~80,470 LOC. 5 cold spots (1 bug, 4 minor). 34 integration test failures (likely related to uncommitted moderation/promo code changes). | |
| 8 | + | Run 19: 1,923 tests passing (1,213 unit + 679 integration + 28 doc + 3 load; 10 ignored), 0 failed. 0 clippy warnings. v0.4.7. ~81,384 LOC. 2 cold spots (0 bugs, 2 minor). Combined with doc fuzz for creator email readiness assessment. | |
| 9 | 9 | ||
| 10 | 10 | ## Scorecard | |
| 11 | 11 | ||
| 12 | 12 | | Dimension | Grade | Notes | | |
| 13 | 13 | |-----------|:-----:|-------| | |
| 14 | - | | Code Quality | A | 3 production `.unwrap()` in git/raw.rs + 1 in helpers.rs (convention violations, not crash risks) | | |
| 15 | - | | Architecture | A- | 4 instances of inline SQL in route handlers (stripe/checkout, dashboard/forms, landing) | | |
| 16 | - | | Testing | A | 1,933 tests, 34 integration failures (uncommitted changes), proptest active | | |
| 14 | + | | Code Quality | A | unwrap() in git/raw.rs fixed. helpers.rs split into formatting/crypto/rate_limit (395 lines from 1,268) | | |
| 15 | + | | Architecture | A | Inline SQL in route handlers still present (4 locations) but minor | | |
| 16 | + | | Testing | A | 1,923 tests, 0 failures. proptest active. Lockout test fixed (auth rate limit fast-tests override) | | |
| 17 | 17 | | Security | A+ | Zero SQL injection vectors, constant-time compare everywhere, fail-closed scanning, CSRF on all forms | | |
| 18 | - | | Performance | A- | analytics.rs query duplication, hash_lookup creates new reqwest::Client per call | | |
| 19 | - | | Documentation | A | Module-level //! on every file, response conventions documented | | |
| 20 | - | | Dependencies | A | All deps at latest stable, async-trait cleanup opportunity (Rust 2024 native async) | | |
| 21 | - | | Frontend | A | Askama auto-escape, all `\|safe` uses verified safe, strong CSP, no raw innerHTML | | |
| 22 | - | | Type Safety | A | 50+ UUID newtypes, validated string types, Cents monetary newtype. Minor: moderation.rs uses raw Uuid | | |
| 23 | - | | Observability | A | 1 missing #[instrument] (api/mod.rs:public_projects), otherwise comprehensive | | |
| 18 | + | | Performance | A | analytics.rs deduplicated (623->468 LOC). hash_lookup uses static reqwest::Client | | |
| 19 | + | | Documentation | A- | Module-level //! on every file. No README.md (CONTRIBUTING.md partially fills role) | | |
| 20 | + | | Dependencies | A- | Most deps current. tokio (1.49->1.50), uuid (1.20->1.22), chrono (0.4.43->0.4.44) pins stale | | |
| 21 | + | | Frontend | A | Askama auto-escape, all `\|safe` uses verified safe, no raw innerHTML. No CSP header (inline onclick pattern) | | |
| 22 | + | | Type Safety | A | 50+ UUID newtypes, validated string types, Cents monetary newtype. moderation.rs still uses raw Uuid | | |
| 23 | + | | Observability | A | Comprehensive #[instrument] coverage. Structured logging throughout | | |
| 24 | 24 | | Concurrency | A | ON CONFLICT, FOR UPDATE, atomic WHERE guards, advisory locks, optimistic versioning | | |
| 25 | - | | Resilience | A+ | Graceful shutdown with hard deadline, migration exit code 2, health monitor with status-transition alerts | | |
| 25 | + | | Resilience | A | Graceful shutdown with hard deadline. One missing timeout: payments/connect.rs:198 raw reqwest call | | |
| 26 | 26 | | API Consistency | A | Documented response conventions, json_error_layer, versioned SyncKit routes | | |
| 27 | - | | Migration Safety | A | 85 additive migrations, IF EXISTS on drops, CHECK constraints | | |
| 28 | - | | Codebase Size | A- | 80K LOC well-organized; helpers.rs (1,268 lines) should be split | | |
| 27 | + | | Migration Safety | A | 87 additive migrations, IF EXISTS on drops, CHECK constraints | | |
| 28 | + | | Codebase Size | A | 81K LOC well-organized. helpers.rs split complete. analytics.rs deduplicated | | |
| 29 | 29 | ||
| 30 | 30 | ## Module Heatmap | |
| 31 | 31 | ||
| @@ -95,18 +95,22 @@ Run 18: 1,933 tests (1,209 unit + 724 integration). 0 clippy warnings. v0.4.6. ~ | |||
| 95 | 95 | ||
| 96 | 96 | ### Cold Spots | |
| 97 | 97 | ||
| 98 | - | 1. **db/moderation.rs type safety (B):** Uses raw `Uuid` for action IDs and `String` for action_type instead of typed newtypes. Only file in db/ without typed IDs. | |
| 99 | - | 2. **routes/git/raw.rs code quality (B):** Three `.unwrap()` calls on `Response::builder().body()` — violates no-unwrap convention. | |
| 100 | - | 3. **db/analytics.rs code quality (B+):** 12 near-identical query blocks across timeseries/comparison functions. Query builder pattern would cut ~150 LOC. | |
| 101 | - | 4. **routes/admin/ CSRF (B):** POST routes rely on AdminUser session + SameSite cookies but no explicit CSRF token validation. | |
| 102 | - | 5. **wam_client.rs testing (B):** Zero unit tests for the WAM HTTP client. | |
| 98 | + | 1. **db/moderation.rs type safety (B):** Uses raw `Uuid` for action IDs and `String` for action_type instead of typed newtypes. Only file in db/ without typed IDs. (Carried from Run 18) | |
| 99 | + | 2. **payments/connect.rs resilience (B):** Missing timeout on raw reqwest call to Stripe resume-subscription API at line 198. Only unprotected outbound HTTP call in the codebase. | |
| 100 | + | ||
| 101 | + | ### Resolved Cold Spots (from Run 18) | |
| 102 | + | - ~~routes/git/raw.rs unwrap()~~ -- Fixed | |
| 103 | + | - ~~db/analytics.rs duplication~~ -- Fixed (Scope enum extraction) | |
| 104 | + | - ~~wam_client.rs testing~~ -- Fixed (5 tests added) | |
| 103 | 105 | ||
| 104 | 106 | ## Mandatory Surprise | |
| 105 | 107 | ||
| 106 | - | **BUG: Sandbox creator tier mismatch.** `db/users.rs:259` inserts `'SmallFiles'` (PascalCase) into the `creator_tier` column, but `impl_str_enum!` maps `SmallFiles => "small_files"` (snake_case). When `auth.rs:178` parses the tier via `.parse().ok()`, the mismatch silently returns `None`. Sandbox users lose their SmallFiles tier privileges — storage limits, file upload permissions, and tier-gated features all fall back to no-tier defaults. Fix: change the SQL literal from `'SmallFiles'` to `'small_files'`. | |
| 108 | + | **Hand-rolled Stripe v2 webhook signature verification.** `payments/webhooks.rs:184-228` implements v2 webhook signature verification from scratch because the `stripe` crate only supports v1. The implementation correctly parses `t=,v1=` headers, rejects timestamps >300s in either direction (replay + clock skew), and uses `hmac::Hmac::verify_slice()` which is constant-time via the `subtle` crate. Both past and future timestamp bounds are checked. Well-tested with 26 unit tests including edge cases (stale, future, wrong secret, within tolerance). | |
| 107 | 109 | ||
| 108 | 110 | ### Previous Surprises | |
| 109 | 111 | ||
| 112 | + | **Run 18:** Sandbox tier mismatch bug (SmallFiles vs small_files). Fixed. | |
| 113 | + | ||
| 110 | 114 | **Run 17:** TOCTOU-safe slug generation with retry loop + advisory lock pattern for sandbox IP cap. | |
| 111 | 115 | ||
| 112 | 116 | **Run 15:** Session touch cache — DashMap with 30s TTL avoids N+1 session queries. | |
| @@ -140,20 +144,15 @@ Zero SQL injection vectors across 200+ queries. Argon2id with explicit params, C | |||
| 140 | 144 | ||
| 141 | 145 | ## Action Items | |
| 142 | 146 | ||
| 143 | - | ### Run 18 (2026-05-01) | |
| 144 | - | ||
| 145 | - | 39. **[HIGH]** Fix sandbox tier: change `'SmallFiles'` to `'small_files'` in `db/users.rs:259` | |
| 146 | - | 40. **[MEDIUM]** Extract inline SQL from route handlers to db/ layer (4 locations listed above) | |
| 147 | - | 41. **[MEDIUM]** Add `ModerationActionId` newtype and `ModerationActionType` enum to `db/moderation.rs` | |
| 148 | - | 42. **[MEDIUM]** Replace `.unwrap()` in `routes/git/raw.rs:80,142,190` with proper error handling | |
| 149 | - | 43. **[MEDIUM]** Add `#[tracing::instrument]` to `routes/api/mod.rs:public_projects` | |
| 150 | - | 44. **[LOW]** Replace production `.unwrap()` at `helpers.rs:52` with `unwrap_or_else` or `HeaderValue::from_static` | |
| 151 | - | 45. **[LOW]** Replace production `.unwrap()` at `monitor.rs:105` with pattern match | |
| 152 | - | 46. **[LOW]** Add unit tests to `wam_client.rs` | |
| 153 | - | 47. **[LOW]** Add explicit cents/dollars format option to CSV import | |
| 154 | - | 48. **[DEFERRED]** Split helpers.rs (~1,268 lines) into focused modules (formatting, crypto, rate_limit) | |
| 155 | - | 49. **[DEFERRED]** Reduce analytics.rs query duplication via builder pattern or macro (~150 LOC savings) | |
| 156 | - | 50. **[DEFERRED]** Remove `async-trait` in favor of Rust 2024 native async traits | |
| 147 | + | ### Run 19 (2026-05-02) | |
| 148 | + | ||
| 149 | + | 51. **[MEDIUM]** Add timeout to `payments/connect.rs:198` raw reqwest call to Stripe resume-subscription API | |
| 150 | + | 52. **[MEDIUM]** Add `ModerationActionId` newtype and `ModerationActionType` enum to `db/moderation.rs` (carried from Run 18 #41) | |
| 151 | + | 53. **[LOW]** Add README.md to server/ with setup instructions and architecture overview link | |
| 152 | + | 54. **[LOW]** Bump dependency pins: tokio 1.49->1.50, uuid 1.20->1.22, chrono 0.4.43->0.4.44, yara-x 1.13->1.14, anyhow 1.0.101->1.0.102 | |
| 153 | + | 55. **[DEFERRED]** Extract inline SQL from route handlers to db/ layer (4 locations, carried from Run 18 #40) | |
| 154 | + | 56. **[DEFERRED]** Remove `async-trait` in favor of Rust 2024 native async traits (carried from Run 18 #50) | |
| 155 | + | 57. **[DEFERRED]** Migrate inline `onclick` handlers to `addEventListener` to enable strict CSP | |
| 157 | 156 | ||
| 158 | 157 | ### Open (blocked on upstream) | |
| 159 | 158 | 23. Monitor aws-sdk-s3 for lru fix (RUSTSEC-2026-0002) | |
| @@ -162,19 +161,27 @@ Zero SQL injection vectors across 200+ queries. Argon2id with explicit params, C | |||
| 162 | 161 | 33. bincode unmaintained (RUSTSEC-2025-0141) — upstream via syntect/yara-x, warning only | |
| 163 | 162 | ||
| 164 | 163 | ### Previously resolved | |
| 165 | - | All items 1-22 and 31-38 from previous audits verified intact. | |
| 164 | + | All items 1-22, 31-38, and most Run 18 items verified intact. | |
| 166 | 165 | ||
| 167 | - | ## Previous Action Item Verification | |
| 166 | + | ## Previous Action Item Verification (Run 18) | |
| 168 | 167 | ||
| 169 | 168 | | # | Item | Status | | |
| 170 | 169 | |---|------|--------| | |
| 171 | - | | 23 | aws-sdk-s3 lru fix | Unfixed (upstream) | | |
| 172 | - | | 24 | async-stripe instant fix | Unfixed (upstream) | | |
| 173 | - | | 25 | aws-sdk-s3 rustls-webpki fix | Unfixed (upstream) | | |
| 174 | - | | 33 | bincode unmaintained | Unfixed (upstream) | | |
| 175 | - | | 34-38 | Run 15 items | All fixed/verified | | |
| 176 | - | ||
| 177 | - | No regressions found. Items 23-25, 33 remain open across 3+ consecutive audits (chronic, but upstream-blocked). | |
| 170 | + | | 39 | Sandbox tier bug (`'SmallFiles'`->`'small_files'`) | Fixed | | |
| 171 | + | | 40 | Extract inline SQL from route handlers | Unfixed (carried as #55) | | |
| 172 | + | | 41 | Moderation typed IDs | Unfixed (carried as #52) | | |
| 173 | + | | 42 | `.unwrap()` in git/raw.rs | Fixed | | |
| 174 | + | | 43 | Missing `#[instrument]` on public_projects | Fixed | | |
| 175 | + | | 44 | `.unwrap()` in helpers.rs | Fixed (helpers.rs split) | | |
| 176 | + | | 45 | `.unwrap()` in monitor.rs | Fixed | | |
| 177 | + | | 46 | wam_client.rs unit tests | Fixed (5 tests added) | | |
| 178 | + | | 47 | CSV import cents/dollars format | Fixed (heuristic removed) | | |
| 179 | + | | 48 | Split helpers.rs | Fixed (1,268->395 lines: formatting.rs, crypto.rs, rate_limit.rs) | | |
| 180 | + | | 49 | Analytics.rs deduplication | Fixed (623->468 lines via Scope enum) | | |
| 181 | + | | 50 | Remove async-trait | Unfixed (carried as #56) | | |
| 182 | + | | 23-25, 33 | Upstream dep advisories | Unfixed (chronic, upstream-blocked) | | |
| 183 | + | ||
| 184 | + | 10 of 12 Run 18 items fixed. 2 carried forward. No regressions. | |
| 178 | 185 | ||
| 179 | 186 | ## Metrics Over Time | |
| 180 | 187 | ||
| @@ -197,6 +204,7 @@ No regressions found. Items 23-25, 33 remain open across 3+ consecutive audits ( | |||
| 197 | 204 | | 2026-04-22 (Run 15 corrected) | ~67,442 | -- | 1,359 | ~20 | 0 | 1 | A | | |
| 198 | 205 | | 2026-04-30 (Run 17) | ~79,334 | -- | 1,861 | ~15.0 | 0 | 0 | A | | |
| 199 | 206 | | 2026-05-01 (Run 18) | ~80,470 | -- | 1,933 (34 int. fail) | ~15.1 | 0 | 5 | A | | |
| 207 | + | | 2026-05-02 (Run 19) | ~81,384 | -- | 1,923 (0 fail) | ~23.6 | 0 | 2 | A | | |
| 200 | 208 | ||
| 201 | 209 | --- | |
| 202 | 210 |
| @@ -23,39 +23,456 @@ Items requiring manual action, external accounts, legal engagement, design decis | |||
| 23 | 23 | ||
| 24 | 24 | --- | |
| 25 | 25 | ||
| 26 | - | ## Content Seeding & Manual Testing | |
| 26 | + | ## Feature Map & Manual Testing (94 features, 2026-05-02) | |
| 27 | 27 | ||
| 28 | - | ### Creator Setup | |
| 29 | - | - [ ] Confirm creator tier is Small Files ($20/mo) | |
| 30 | - | - [ ] Confirm Stripe Connect onboarding complete (live mode) | |
| 28 | + | Feature map generated from full codebase walk. Every user-facing feature enumerated. | |
| 31 | 29 | ||
| 32 | - | ### Project: GoingsOn | |
| 33 | - | - [ ] Create subscription tier: "Cloud Sync" ($3/mo) — not yet created | |
| 30 | + | ### 1. Authentication & Account Security | |
| 34 | 31 | ||
| 35 | - | ### Project: audiofiles | |
| 36 | - | - [ ] Enable license keys (test activation flow) | |
| 37 | - | - [ ] Create a test discount code (e.g. LAUNCH50, 50% off) | |
| 32 | + | - [ ] **Sign up** — 5-step wizard (username, email, password, profile, complete) | |
| 33 | + | - [ ] Happy path: account created, verification email arrives | |
| 34 | + | - [ ] Breached password advisory warning (non-blocking) | |
| 35 | + | - [ ] Username validation (availability, format, 3-50 chars) | |
| 36 | + | - [ ] Invite code redemption grants instant creator access | |
| 37 | + | - [ ] Welcome email arrives | |
| 38 | + | - [ ] **Email verification** — click link in email | |
| 39 | + | - [ ] Happy path: email marked verified | |
| 40 | + | - [ ] Guest purchases auto-attached to account | |
| 41 | + | - [ ] Resend verification email works | |
| 42 | + | - [ ] **Email/password login** — username or email + password | |
| 43 | + | - [ ] Happy path: redirects to dashboard | |
| 44 | + | - [ ] "Remember me" checkbox persists session | |
| 45 | + | - [ ] Wrong password shows error (no user enumeration) | |
| 46 | + | - [ ] Account lockout after N failures | |
| 47 | + | - [ ] Lockout email with one-time login link arrives | |
| 48 | + | - [ ] **Passkey login (WebAuthn)** — passwordless discoverable credentials | |
| 49 | + | - [ ] Register passkey from dashboard | |
| 50 | + | - [ ] Login without username via passkey | |
| 51 | + | - [ ] Rename passkey | |
| 52 | + | - [ ] Delete passkey | |
| 53 | + | - [ ] Max 20 passkeys enforced | |
| 54 | + | - [ ] **Two-factor authentication (TOTP)** — authenticator app | |
| 55 | + | - [ ] Setup: QR code displayed, backup codes generated | |
| 56 | + | - [ ] Confirm: first TOTP code enables 2FA | |
| 57 | + | - [ ] Login requires 2FA code after password | |
| 58 | + | - [ ] Backup code works as alternative | |
| 59 | + | - [ ] Disable 2FA (requires password) | |
| 60 | + | - [ ] Regenerate backup codes (requires password) | |
| 61 | + | - [ ] **Password reset** — email link flow | |
| 62 | + | - [ ] Forgot password form always returns success (no enumeration) | |
| 63 | + | - [ ] Reset link arrives, form works | |
| 64 | + | - [ ] New password set, all other sessions revoked | |
| 65 | + | - [ ] Link invalidated if password already changed | |
| 66 | + | - [ ] **One-time login link** — email-based single-use login | |
| 67 | + | - [ ] Link works once | |
| 68 | + | - [ ] Link consumed atomically (no reuse) | |
| 69 | + | - [ ] **Change password** — from dashboard | |
| 70 | + | - [ ] Requires current password | |
| 71 | + | - [ ] All other sessions revoked on change | |
| 72 | + | - [ ] **Session management** — view and revoke | |
| 73 | + | - [ ] List active sessions with device info | |
| 74 | + | - [ ] Revoke specific session | |
| 75 | + | - [ ] Revoke all other sessions | |
| 76 | + | - [ ] **New device login alert** — email on new device | |
| 77 | + | - [ ] Alert sent when >1 active session and enabled | |
| 78 | + | - [ ] **Logout** — destroys session, redirects to landing | |
| 79 | + | - [ ] **Email unsubscribe** — signed link in emails | |
| 80 | + | - [ ] One-click unsubscribe (RFC 8058) | |
| 81 | + | - [ ] Per-notification-type opt-out | |
| 38 | 82 | ||
| 39 | - | ### Cross-Project | |
| 40 | - | - [ ] Add custom links (source code link, support@makenot.work — currently profile has Twitter/Mastodon/htpy.app) | |
| 41 | - | - [ ] Test free download flow (GO), PWYW flow (BB), purchase flow (AF), subscription flow (GO) | |
| 42 | - | - [ ] Test discount code on AF purchase | |
| 43 | - | - [ ] Test license key delivery after AF purchase | |
| 44 | - | - [ ] Capture screenshots for docs (dashboard, audio player, discover, pricing, git browser) — or replace with sandbox links | |
| 83 | + | ### 2. Profile & Settings | |
| 84 | + | ||
| 85 | + | - [ ] **Update profile** — display name and bio | |
| 86 | + | - [ ] **Notification preferences** — toggle email types (sales, followers, issues, etc.) | |
| 87 | + | - [ ] **Custom profile links** — add/reorder social links on profile | |
| 88 | + | - [ ] Add custom links (source code, support@makenot.work) | |
| 89 | + | - [ ] Reorder links | |
| 90 | + | - [ ] Delete links | |
| 91 | + | - [ ] **SSH key management** — add/remove keys for git push | |
| 92 | + | - [ ] **Stripe tax toggle** — enable/disable automatic tax calculation | |
| 93 | + | - [ ] **Stripe disconnect** — disconnect Stripe account | |
| 94 | + | ||
| 95 | + | ### 3. Account Lifecycle | |
| 96 | + | ||
| 97 | + | - [ ] **Account deactivation** — suspend own account (hides profile/projects) | |
| 98 | + | - [ ] Deactivate works | |
| 99 | + | - [ ] Reactivate restores everything | |
| 100 | + | - [ ] **Account deletion** — request via email confirmation | |
| 101 | + | - [ ] Email confirmation link arrives | |
| 102 | + | - [ ] Confirm deletion page prevents accidental deletion | |
| 103 | + | - [ ] Creator with sales: 90-day content grace period | |
| 104 | + | - [ ] Buyers notified on creator deletion | |
| 105 | + | - [ ] Direct API deletion (no email) also works | |
| 106 | + | - [ ] **Sandbox mode** — 1-hour ephemeral demo, no signup required | |
| 107 | + | - [ ] Sandbox account created and functional | |
| 108 | + | - [ ] Auto-expires after 1 hour | |
| 109 | + | ||
| 110 | + | ### 4. Creator Tier & Stripe Setup | |
| 111 | + | ||
| 112 | + | - [ ] **Creator tier selection** — Basic $10, Small Files $20, Big Files $30, Everything $60 | |
| 113 | + | - [ ] Confirm creator tier is Small Files ($20/mo) | |
| 114 | + | - [ ] Upgrade/downgrade prorated | |
| 115 | + | - [ ] Feature gates enforce tier limits | |
| 116 | + | - [ ] **Stripe Connect onboarding** — connect Stripe to receive payments | |
| 117 | + | - [ ] Confirm Stripe Connect onboarding complete (live mode) | |
| 118 | + | - [ ] Disclaimer page before onboarding | |
| 119 | + | - [ ] Stripe-hosted onboarding completes | |
| 120 | + | - [ ] Return redirect works | |
| 121 | + | ||
| 122 | + | ### 5. Projects & Storefronts | |
| 123 | + | ||
| 124 | + | - [ ] **Project creation wizard** — 5-step guided flow (basics, appearance, monetization, content, preview) | |
| 125 | + | - [ ] Create project with title, slug, category, description | |
| 126 | + | - [ ] Cover image upload | |
| 127 | + | - [ ] Feature selection (which content types to enable) | |
| 128 | + | - [ ] Mailing list auto-created | |
| 129 | + | - [ ] **Project editing** — update all fields | |
| 130 | + | - [ ] Title, description, category, visibility | |
| 131 | + | - [ ] **Project deletion** — permanent, items become inaccessible | |
| 132 | + | - [ ] **Project labels** — apply custom labels for filtering | |
| 133 | + | - [ ] **Project members & revenue splits** — add collaborators, split revenue % | |
| 134 | + | - [ ] Add member | |
| 135 | + | - [ ] Remove member | |
| 136 | + | - [ ] Revenue split recorded | |
| 137 | + | - [ ] **Git repository linking** — link repos to projects | |
| 138 | + | - [ ] Link repo | |
| 139 | + | - [ ] Manage collaborator access | |
| 140 | + | - [ ] Unlink repo | |
| 141 | + | ||
| 142 | + | ### 6. Items (Products) | |
| 143 | + | ||
| 144 | + | - [ ] **Item creation wizard** — 8-step guided flow (type, details, appearance, content, sections, pricing, distribution, preview) | |
| 145 | + | - [ ] Create item of each type: Audio, Text, Video, Digital, Plugin, Bundle | |
| 146 | + | - [ ] Set title, description, price, cover image | |
| 147 | + | - [ ] AI tier disclosure (Handmade/Assisted/Generated) | |
| 148 | + | - [ ] **Item editing** — update all fields | |
| 149 | + | - [ ] Title, description, price, tags, cover, release date, credits | |
| 150 | + | - [ ] **Item deletion** — permanent, buyers lose access | |
| 151 | + | - [ ] **Bulk item operations** — publish, unpublish, delete multiple | |
| 152 | + | - [ ] **Item duplication** — clone existing item | |
| 153 | + | - [ ] **Move item** — between projects | |
| 154 | + | - [ ] **Item tags** — add/remove with autocomplete, set primary tag, suggestions | |
| 155 | + | - [ ] **Item bundles** — group items for combined sale | |
| 156 | + | - [ ] Add child items | |
| 157 | + | - [ ] Unlisted items only available in bundle | |
| 158 | + | - [ ] Bundle listing visibility toggle | |
| 159 | + | - [ ] **Chapters** — timestamp markers for audio/video navigation | |
| 160 | + | - [ ] Create, edit, delete, reorder chapters | |
| 161 | + | - [ ] **Content sections** — reorderable structured sections | |
| 162 | + | - [ ] Create, edit, delete, reorder sections | |
| 163 | + | - [ ] **Item versions/releases** — version numbering with changelogs | |
| 164 | + | - [ ] Create version with changelog and file | |
| 165 | + | - [ ] **Scheduled publishing** — set future publish date | |
| 166 | + | - [ ] **Text content editor** — markdown with live preview | |
| 167 | + | ||
| 168 | + | ### 7. File Storage & Media | |
| 169 | + | ||
| 170 | + | - [ ] **File upload** — presigned S3 URL + confirm pattern | |
| 171 | + | - [ ] Upload file within tier size limit | |
| 172 | + | - [ ] Tier-based size limits enforced | |
| 173 | + | - [ ] Cover image upload (project + item) | |
| 174 | + | - [ ] **File download & streaming** — authenticated URLs | |
| 175 | + | - [ ] Stream audio in browser player | |
| 176 | + | - [ ] Download version file | |
| 177 | + | - [ ] **Guest download** — token-based post-purchase download | |
| 178 | + | - [ ] Download works without account | |
| 179 | + | - [ ] **Media library** — reusable clips/files organized by folder | |
| 180 | + | - [ ] Upload media | |
| 181 | + | - [ ] List by folder | |
| 182 | + | - [ ] Delete media | |
| 183 | + | - [ ] **Content insertions** — pre/mid/post roll placement in items | |
| 184 | + | - [ ] Add insertion to item | |
| 185 | + | - [ ] Remove insertion | |
| 186 | + | - [ ] Position-based placement works | |
| 187 | + | - [ ] **Malware scanning** — ClamAV + YARA + hash lookup before availability | |
| 188 | + | ||
| 189 | + | ### 8. Monetization & Payments | |
| 190 | + | ||
| 191 | + | - [ ] **One-time item purchase** — fixed or PWYW price via Stripe, 0% platform fee | |
| 192 | + | - [ ] Purchase flow (AF): fixed price item checkout completes | |
| 193 | + | - [ ] PWYW flow (BB): pay-what-you-want with minimum | |
| 194 | + | - [ ] Free download flow (GO): free item claimed | |
| 195 | + | - [ ] **Guest checkout** — purchase without account | |
| 196 | + | - [ ] Email receipt with download link arrives | |
| 197 | + | - [ ] CORS works for embedded checkouts | |
| 198 | + | - [ ] **Direct purchase link** — minimal /buy/ page for link-in-bio | |
| 199 | + | - [ ] **Subscription tiers** — per-project monthly recurring | |
| 200 | + | - [ ] Create subscription tier | |
| 201 | + | - [ ] Subscription flow (GO): subscriber can access gated content | |
| 202 | + | - [ ] Create subscription tier: "Cloud Sync" ($3/mo) on GoingsOn | |
| 203 | + | - [ ] Toggle tier active/inactive | |
| 204 | + | - [ ] **Fan+ subscription** — platform-wide monthly subscription | |
| 205 | + | - [ ] Fan+ checkout completes | |
| 206 | + | - [ ] Fan+ status visible in session | |
| 207 | + | - [ ] **Tips / donations** — $1-$10,000 one-time tip with optional message | |
| 208 | + | - [ ] Tip flow completes | |
| 209 | + | - [ ] Tip shows in creator dashboard with sender/amount/message | |
| 210 | + | - [ ] **Promo codes** — discount (%, $), free-access, free-trial | |
| 211 | + | - [ ] Create discount code (e.g. LAUNCH50, 50% off) | |
| 212 | + | - [ ] Apply discount code on AF purchase | |
| 213 | + | - [ ] Free-access code claim works | |
| 214 | + | - [ ] Free-trial code works on subscription | |
| 215 | + | - [ ] Usage limits enforced | |
| 216 | + | - [ ] Expiry enforced | |
| 217 | + | - [ ] Item/project/platform scoping works | |
| 218 | + | - [ ] **License keys** — generate, validate, activate per machine | |
| 219 | + | - [ ] Enable license keys on audiofiles | |
| 220 | + | - [ ] License key delivery after AF purchase | |
| 221 | + | - [ ] Validate key (public API) | |
| 222 | + | - [ ] Activate on machine | |
| 223 | + | - [ ] Deactivation works | |
| 224 | + | - [ ] Activation limit enforced | |
| 225 | + | - [ ] Revoke key (creator) | |
| 226 | + | - [ ] Key status check (public API) | |
| 227 | + | - [ ] **Creator payout & balance** — real-time Stripe balance | |
| 228 | + | - [ ] Available vs pending display | |
| 229 | + | - [ ] Transaction history visible | |
| 230 | + | ||
| 231 | + | ### 9. Discovery & Browsing | |
| 232 | + | ||
| 233 | + | - [ ] **Discover page** — search + faceted filters | |
| 234 | + | - [ ] Keyword search returns results | |
| 235 | + | - [ ] Filter by item type | |
| 236 | + | - [ ] Filter by tag/category/label | |
| 237 | + | - [ ] Filter by price range | |
| 238 | + | - [ ] Filter by AI tier | |
| 239 | + | - [ ] Sort: featured, newest, popular, price | |
| 240 | + | - [ ] Pagination works | |
| 241 | + | - [ ] Mode switch: items vs projects | |
| 242 | + | - [ ] **Tag tree browser** — hierarchical tag navigation with breadcrumbs | |
| 243 | + | - [ ] **Personalized feed** — activity from followed creators/projects | |
| 244 | + | - [ ] Feed shows items from followed creators | |
| 245 | + | - [ ] Pagination works | |
| 246 | + | - [ ] **Creator profile page** — /u/{username} | |
| 247 | + | - [ ] Bio, avatar, projects, links, follower count displayed | |
| 248 | + | - [ ] Tip button visible (if Stripe connected) | |
| 249 | + | - [ ] **Project storefront page** — /p/{slug} | |
| 250 | + | - [ ] Items, blog, subscription tiers, git repos, community link visible | |
| 251 | + | - [ ] Follow button works | |
| 252 | + | - [ ] **Item detail page** — /i/{item_id} | |
| 253 | + | - [ ] Audio player with chapters works | |
| 254 | + | - [ ] Text reader renders markdown | |
| 255 | + | - [ ] Purchase button with promo code entry | |
| 256 | + | - [ ] Version history visible | |
| 257 | + | - [ ] **Collection page** — /c/{username}/{slug} | |
| 258 | + | - [ ] Curated items displayed | |
| 259 | + | ||
| 260 | + | ### 10. Content Marketing & Community | |
| 261 | + | ||
| 262 | + | - [ ] **Blog publishing** — markdown posts per project | |
| 263 | + | - [ ] Create blog post | |
| 264 | + | - [ ] Edit blog post | |
| 265 | + | - [ ] Delete blog post | |
| 266 | + | - [ ] Scheduled publishing | |
| 267 | + | - [ ] Web-only option (skip email) | |
| 268 | + | - [ ] Follower announcement sent | |
| 269 | + | - [ ] **RSS feeds** — 4 types | |
| 270 | + | - [ ] Creator feed: /u/{username}/rss | |
| 271 | + | - [ ] Project feed: /p/{slug}/rss | |
| 272 | + | - [ ] Blog feed: /p/{slug}/blog/feed.xml | |
| 273 | + | - [ ] Personal signed feed: /feed/{user_id}?sig=... | |
| 274 | + | - [ ] **Follower system** — follow users/projects/tags | |
| 275 | + | - [ ] Follow creator | |
| 276 | + | - [ ] Follow project | |
| 277 | + | - [ ] Unfollow works | |
| 278 | + | - [ ] Follower notifications arrive | |
| 279 | + | - [ ] **Mailing lists & broadcasts** — auto-created per project | |
| 280 | + | - [ ] Broadcast message to all followers | |
| 281 | + | - [ ] **Collections** — curated item groupings | |
| 282 | + | - [ ] Create collection (up to 100) | |
| 283 | + | - [ ] Add items (up to 1,000 per collection) | |
| 284 | + | - [ ] Reorder items | |
| 285 | + | - [ ] Public/private toggle | |
| 286 | + | - [ ] Delete collection (items unaffected) | |
| 287 | + | ||
| 288 | + | ### 11. Embeds & Distribution | |
| 289 | + | ||
| 290 | + | - [ ] **Embed widgets** — self-contained HTML for external sites | |
| 291 | + | - [ ] Item button embed: /embed/i/{id}/button | |
| 292 | + | - [ ] Item card embed: /embed/i/{id}/card | |
| 293 | + | - [ ] Item player embed: /embed/i/{id}/player | |
| 294 | + | - [ ] Project card embed: /embed/p/{slug}/card | |
| 295 | + | - [ ] Tip button embed: /embed/u/{username}/tip | |
| 296 | + | - [ ] **Custom domains** — point domain to creator storefront | |
| 297 | + | - [ ] Add custom domain | |
| 298 | + | - [ ] DNS TXT record verification | |
| 299 | + | - [ ] TLS via Caddy works | |
| 300 | + | - [ ] Fallback routing to user/project/item pages | |
| 301 | + | ||
| 302 | + | ### 12. Analytics & Data | |
| 45 | 303 | ||
| 46 | - | ### SyncKit Production Testing | |
| 47 | - | - [ ] Test sync across 2+ GO instances on real server | |
| 304 | + | - [ ] **Analytics dashboard** — 3 levels (user, project, item) | |
| 305 | + | - [ ] User-level: aggregated revenue, sales, followers | |
| 306 | + | - [ ] Project-level: revenue chart, top items, time range selector | |
| 307 | + | - [ ] Item-level: play count, download count | |
| 308 | + | - [ ] Time ranges: 7d / 30d / 90d / all | |
| 309 | + | - [ ] **Data export** — no lock-in guarantee | |
| 310 | + | - [ ] Export projects (JSON) | |
| 311 | + | - [ ] Export sales (CSV) | |
| 312 | + | - [ ] Export purchases (CSV) | |
| 313 | + | - [ ] Export splits (CSV) | |
| 314 | + | - [ ] Export followers (CSV) | |
| 315 | + | - [ ] Export subscriptions (CSV) | |
| 316 | + | - [ ] Export content (ZIP) | |
| 317 | + | - [ ] **CSV import** — bulk item creation | |
| 318 | + | - [ ] Start import job | |
| 319 | + | - [ ] Progress tracking | |
| 320 | + | - [ ] Error handling (partial success) | |
| 321 | + | - [ ] **Contact sharing & revocation** — buyer-side control | |
| 322 | + | - [ ] Buyer can revoke contact sharing with a creator | |
| 48 | 323 | ||
| 49 | - | ### OTA | |
| 50 | - | - [ ] End-to-end test: build signed GO release, upload artifact, verify auto-update check returns 200 | |
| 324 | + | ### 13. Git Source Browser | |
| 325 | + | ||
| 326 | + | - [ ] **Repository browser** — web UI for git repos | |
| 327 | + | - [ ] Repo overview with README | |
| 328 | + | - [ ] File tree navigation with breadcrumbs | |
| 329 | + | - [ ] File viewer with syntax highlighting | |
| 330 | + | - [ ] Commit log (paginated) | |
| 331 | + | - [ ] Commit detail with inline diffs | |
| 332 | + | - [ ] Blame view | |
| 333 | + | - [ ] File history | |
| 334 | + | - [ ] Raw file download | |
| 335 | + | - [ ] Ref selector (branches/tags) | |
| 336 | + | - [ ] **Smart HTTP clone** — `git clone https://makenot.work/git/owner/repo.git` | |
| 337 | + | - [ ] **Email-based issue tracker** — create/reply via email, read-only web UI | |
| 338 | + | - [ ] Issue list with open/closed filter | |
| 339 | + | - [ ] Issue detail with comments | |
| 340 | + | - [ ] Create issue via email (owner+repo@issues.makenot.work) | |
| 341 | + | - [ ] Reply via email | |
| 342 | + | - [ ] Commit message references (closes #N) | |
| 343 | + | - [ ] Repo issue settings | |
| 344 | + | - [ ] **Email patch submission** — git send-email to MT threads | |
| 345 | + | - [ ] Patch email routed to discussion thread | |
| 346 | + | ||
| 347 | + | ### 14. SyncKit (E2E Encrypted Cloud Sync) | |
| 348 | + | ||
| 349 | + | - [ ] **SyncKit auth** — email/password + API key, or OAuth2 PKCE | |
| 350 | + | - [ ] **Push/pull sync** — bidirectional encrypted changelog | |
| 351 | + | - [ ] Push changes | |
| 352 | + | - [ ] Pull changes with cursor-based pagination | |
| 353 | + | - [ ] Table name filter for selective pull | |
| 354 | + | - [ ] Idempotent push via batch_id | |
| 355 | + | - [ ] **Device management** — register, list, delete devices | |
| 356 | + | - [ ] **E2E key storage** — encrypted keys with optimistic concurrency | |
| 357 | + | - [ ] Store key | |
| 358 | + | - [ ] Retrieve key | |
| 359 | + | - [ ] Version conflict returns 409 | |
| 360 | + | - [ ] **Blob storage** — encrypted blobs with hash dedup | |
| 361 | + | - [ ] Upload blob | |
| 362 | + | - [ ] Download blob | |
| 363 | + | - [ ] Duplicate hash skips re-upload | |
| 364 | + | - [ ] **App management** — create apps, generate API keys | |
| 365 | + | - [ ] Create sync app | |
| 366 | + | - [ ] Regenerate API key | |
| 367 | + | - [ ] Link app to project/item | |
| 368 | + | - [ ] Set custom slug | |
| 369 | + | - [ ] Delete app | |
| 370 | + | - [ ] **SSE push notifications** — real-time sync events | |
| 371 | + | - [ ] Connect to SSE endpoint | |
| 372 | + | - [ ] Receive "changed" events | |
| 373 | + | - [ ] **Key rotation** — rotate master encryption key | |
| 374 | + | - [ ] Begin rotation, re-encrypt entries in batches, complete | |
| 375 | + | - [ ] Verify other device can pull mixed-key entries during rotation | |
| 376 | + | - [ ] Verify new device setup after rotation uses new key | |
| 377 | + | - [ ] **SyncKit production test** — test sync across 2+ GO instances on real server | |
| 378 | + | ||
| 379 | + | ### 15. OTA Updates | |
| 380 | + | ||
| 381 | + | - [ ] **Release management** — create releases with semver, signatures, multi-platform | |
| 382 | + | - [ ] Create release with artifact | |
| 383 | + | - [ ] List releases | |
| 384 | + | - [ ] Delete release | |
| 385 | + | - [ ] **Update check (public)** — Tauri-compatible endpoint | |
| 386 | + | - [ ] Build signed GO release, upload artifact, verify auto-update check returns 200 | |
| 387 | + | - [ ] 204 when already on latest version | |
| 388 | + | - [ ] Download artifact via presigned URL | |
| 389 | + | ||
| 390 | + | ### 16. OAuth2 Authorization Server | |
| 391 | + | ||
| 392 | + | - [ ] **OAuth2 PKCE flow** — third-party app authentication | |
| 393 | + | - [ ] Authorize page renders | |
| 394 | + | - [ ] Grant authorization | |
| 395 | + | - [ ] Token exchange with PKCE verifier | |
| 396 | + | - [ ] Userinfo returns username, display_name, avatar | |
| 397 | + | - [ ] Localhost redirect URIs auto-allowed | |
| 398 | + | ||
| 399 | + | ### 17. Admin Tools | |
| 400 | + | ||
| 401 | + | - [ ] **Waitlist management** — approve/spam-mark applications, lottery | |
| 402 | + | - [ ] **User moderation** — warn, suspend, unsuspend, terminate | |
| 403 | + | - [ ] Trust/untrust for auto-upload approval | |
| 404 | + | - [ ] Per-user file size override | |
| 405 | + | - [ ] **Upload review queue** — approve/reject items and versions | |
| 406 | + | - [ ] **Report resolution & appeals** — resolve reports, item removal/restoration, decide appeals | |
| 407 | + | - [ ] **Platform labels** — create/manage labels for curation | |
| 408 | + | - [ ] **Metrics dashboard** — uptime, request counts, error rates, DB pool stats | |
| 409 | + | - [ ] **MT community provisioning** — batch-provision communities for projects | |
| 410 | + | ||
| 411 | + | ### 18. Public Pages & Documentation | |
| 412 | + | ||
| 413 | + | - [ ] **Landing page** — platform overview, creator count, item count | |
| 414 | + | - [ ] **Pricing calculator** — interactive comparison with competitors | |
| 415 | + | - [ ] **Use cases page** — creator type showcase | |
| 416 | + | - [ ] **Health/status page** — public uptime at /health | |
| 417 | + | - [ ] **Creator waves page** — invitation wave history at /creators | |
| 418 | + | - [ ] **Documentation system** — searchable docs at /docs | |
| 419 | + | - [ ] Section/subsection navigation | |
| 420 | + | - [ ] Search index (JSON) | |
| 421 | + | - [ ] **Changelog** — platform changelog at /changelog | |
| 422 | + | - [ ] **Content reporting** — report problematic content | |
| 423 | + | - [ ] Report submission | |
| 424 | + | - [ ] Appeal suspension | |
| 425 | + | - [ ] **Support tickets** — submit from dashboard | |
| 426 | + | ||
| 427 | + | ### 19. Buyer Features | |
| 428 | + | ||
| 429 | + | - [ ] **Buyer library** — purchases, subscriptions, collections, contacts, communities | |
| 430 | + | - [ ] Purchases tab: download links | |
| 431 | + | - [ ] Subscriptions tab: active subs, manage, cancel | |
| 432 | + | - [ ] Collections tab: personal curated lists | |
| 433 | + | - [ ] Contacts tab: shared creators | |
| 434 | + | - [ ] Communities tab: MT memberships | |
| 435 | + | - [ ] **Waitlist application** — apply to join creator waitlist | |
| 436 | + | - [ ] **Invite code redemption** — use invite code during signup | |
| 437 | + | ||
| 438 | + | ### 20. Documentation Gap Checklist | |
| 439 | + | ||
| 440 | + | Features that exist in code but lack public documentation: | |
| 441 | + | ||
| 442 | + | - [x] Write guide for **git source browser** (web browsing, SSH clone, smart HTTP) — expanded git.md with HTTPS cloning, collaborators, issues, patches | |
| 443 | + | - [x] Write guide for **email-based issue tracker** (unique email-driven feature) — added to git.md | |
| 444 | + | - [x] Write guide for **email patch submission** (git send-email to MT) — added to git.md | |
| 445 | + | - [x] Write guide for **embed widgets** (button/card/player embeds) — new embeds.md | |
| 446 | + | - [x] Write guide for **media library** (dashboard feature for reusable clips) — new media-library.md | |
| 447 | + | - [x] Write guide for **CSV import** (bulk item creation) — new import.md | |
| 448 | + | - [x] Write guide for **custom profile links** (social links on profile) — expanded profile.md Links section | |
| 449 | + | - [x] Expand **sandbox mode** guide — already comprehensive (sandbox.md covers starting, features, limits, converting) | |
| 450 | + | - [x] Expand **passkey setup** guide — already detailed in security.md (setup, login, managing, 20 passkey limit) | |
| 451 | + | - [x] Write guide for **password reset flow** (step-by-step) — new password-reset.md | |
| 452 | + | - [x] Write guide for **account deactivation** (temporary vs permanent deletion) — new account-lifecycle.md | |
| 453 | + | - [x] Write guide for **personalized feed** (/feed page) — new feed.md | |
| 454 | + | - [x] Write guide for **content insertions** (pre/mid/post roll for audio) — new content-insertions.md | |
| 455 | + | ||
| 456 | + | ### 21. Documented-But-Not-Implemented Tracker | |
| 457 | + | ||
| 458 | + | Features documented in public docs that don't exist in code yet: | |
| 459 | + | ||
| 460 | + | - [ ] **Live streaming** (Everything tier, "coming soon" in docs) | |
| 461 | + | - [ ] **Earn-back credit program** (mentioned in FAQ) | |
| 462 | + | - [ ] **Content archive guarantee** (12+ month content stays live after cancel) | |
| 463 | + | - [ ] **HLS adaptive bitrate** (on roadmap) | |
| 464 | + | - [ ] **Audio transcoding** (on roadmap) | |
| 465 | + | - [ ] **Mobile apps** (on roadmap) | |
| 51 | 466 | ||
| 52 | 467 | ### Sign-Off | |
| 468 | + | ||
| 53 | 469 | - [ ] MNW `deploy/human_testing.md` sign-off table filled | |
| 54 | 470 | - [ ] GO `docs/human_testing.md` sign-off table filled | |
| 55 | 471 | - [ ] AF `human_testing.md` sign-off table filled | |
| 56 | 472 | - [ ] All P0 items pass across all projects | |
| 57 | 473 | - [ ] No panics or 500s in MNW server logs | |
| 58 | 474 | - [ ] Backup verified within last 24 hours | |
| 475 | + | - [ ] Capture screenshots for docs (dashboard, audio player, discover, pricing, git browser) — or replace with sandbox links | |
| 59 | 476 | ||
| 60 | 477 | --- | |
| 61 | 478 |
| @@ -0,0 +1,71 @@ | |||
| 1 | + | # DONE: Add App + SyncKit Revenue to Financial Projections | |
| 2 | + | ||
| 3 | + | **Completed 2026-05-03.** App sync revenue added to `financial_dashboard.md` (adoption scenarios, combined break-even, impact on sustainable/comfortable thresholds) and `economics.md` (app sync revenue section, See Also links). SyncKit SDK noted as future stream, not yet in projections. | |
| 4 | + | ||
| 5 | + | ## What's missing | |
| 6 | + | ||
| 7 | + | The financial dashboard (`financial_dashboard.md`) and economics model (`economics.md`) only project revenue from **creator subscriptions** and **Fan+**. They do not include revenue from the three desktop apps or a productized SyncKit SDK. | |
| 8 | + | ||
| 9 | + | These streams have near-zero marginal cost since the SyncKit infrastructure already exists and runs on the same Hetzner VPS. Including them will lower the break-even creator count and improve runway projections. | |
| 10 | + | ||
| 11 | + | ## Revenue streams to add | |
| 12 | + | ||
| 13 | + | ### 1. GoingsOn sync | |
| 14 | + | - Source: `app_sync_pricing.md` | |
| 15 | + | - Price: $2/month or $15/year | |
| 16 | + | - Net after Stripe: ~$1.64/month or ~$14.26/year ($1.19/month effective) | |
| 17 | + | - Infra cost per user: negligible (metadata only, 1-5 MB) | |
| 18 | + | - Margin: ~80%+ | |
| 19 | + | ||
| 20 | + | ### 2. Balanced Breakfast sync | |
| 21 | + | - Source: `app_sync_pricing.md` | |
| 22 | + | - Price: $1/month or $8/year | |
| 23 | + | - Net after Stripe: ~$0.67/month or ~$7.47/year ($0.62/month effective) | |
| 24 | + | - Infra cost per user: negligible (~1 MB per user) | |
| 25 | + | - Margin: ~90%+ | |
| 26 | + | ||
| 27 | + | ### 3. audiofiles sync (blob tiers) | |
| 28 | + | - Source: `app_sync_pricing.md` | |
| 29 | + | - Price: $1-8/month or $10-80/year (tiered by storage) | |
| 30 | + | - Margins: 58-83% depending on tier | |
| 31 | + | - This is the only app with meaningful per-user infra cost (S3 storage for sample files) | |
| 32 | + | ||
| 33 | + | ### 4. SyncKit SDK (B2B, future) | |
| 34 | + | - Source: `synckit_pricing.md` | |
| 35 | + | - Not yet productized, but planned | |
| 36 | + | - Revenue from indie developers using SyncKit as sync-as-a-service | |
| 37 | + | - Pricing TBD but model exists in synckit_pricing.md | |
| 38 | + | ||
| 39 | + | ## What to update | |
| 40 | + | ||
| 41 | + | ### `financial_dashboard.md` | |
| 42 | + | - Add app sync revenue section alongside creator subscriptions and Fan+ | |
| 43 | + | - Model conservative, moderate, and optimistic adoption scenarios | |
| 44 | + | - Recalculate break-even and self-sustaining thresholds with combined revenue | |
| 45 | + | ||
| 46 | + | ### `economics.md` | |
| 47 | + | - Add section for app revenue streams | |
| 48 | + | - Note that these are independent of creator platform growth (different user base) | |
| 49 | + | ||
| 50 | + | ## Suggested scenarios to model | |
| 51 | + | ||
| 52 | + | | Scenario | GO users | BB users | AF users (avg $3/mo) | Monthly app revenue | | |
| 53 | + | |----------|----------|----------|----------------------|---------------------| | |
| 54 | + | | Conservative (6 mo) | 50 | 30 | 20 | ~$150 | | |
| 55 | + | | Moderate (12 mo) | 200 | 100 | 50 | ~$620 | | |
| 56 | + | | Optimistic (18 mo) | 500 | 300 | 150 | ~$1,650 | | |
| 57 | + | ||
| 58 | + | ### Impact on break-even | |
| 59 | + | ||
| 60 | + | Current break-even: ~32-36 creators (covers ~$600/month fixed costs from creator subs alone). | |
| 61 | + | ||
| 62 | + | If app sync revenue covers infrastructure costs: | |
| 63 | + | - At moderate adoption ($620/month): infra fully covered by apps. Creator subscriptions become pure margin. | |
| 64 | + | - Break-even creator count drops to effectively **0 for infrastructure** — first creator subscription dollar is profit. | |
| 65 | + | - Self-sustaining threshold (covers $3K salary + infra) drops from ~295 creators to ~200-220 creators. | |
| 66 | + | ||
| 67 | + | ## Notes | |
| 68 | + | - Apps are distributed independently of the creator platform. App users ≠ creator platform users. These are separate acquisition funnels. | |
| 69 | + | - GoingsOn is the most likely to drive sync revenue early (productivity apps have higher willingness to pay for sync than feed readers). | |
| 70 | + | - audiofiles has the highest per-user revenue potential but the smallest addressable market. | |
| 71 | + | - Annual billing should be pushed over monthly — better margins due to Stripe fee structure. |
| @@ -0,0 +1,91 @@ | |||
| 1 | + | # App Sync Pricing | |
| 2 | + | ||
| 3 | + | How SyncKit cloud sync is priced for MNW desktop apps (GO, BB, AF). This is consumer-facing pricing, separate from the B2B developer pricing in [synckit_pricing.md](../../synckit_pricing.md). | |
| 4 | + | ||
| 5 | + | ## Guiding Principles | |
| 6 | + | ||
| 7 | + | - Annual billing preferred. Small monthly charges lose a disproportionate amount to Stripe's $0.30 per-transaction fee. Annual pricing passes that savings to the user. | |
| 8 | + | - Priced relative to actual costs where costs are meaningful (AF blob tiers). Priced for development sustainability where costs are negligible (BB, GO metadata sync). | |
| 9 | + | - No overages, ever. When storage is full, sync degrades gracefully. | |
| 10 | + | - Metadata sync is free for AF (the only app with a separate blob tier). BB and GO sync metadata only, so their subscription covers everything. | |
| 11 | + | ||
| 12 | + | ## Balanced Breakfast | |
| 13 | + | ||
| 14 | + | **App price:** Free. | |
| 15 | + | **Sync is the only monetization.** | |
| 16 | + | ||
| 17 | + | BB syncs ~1 MB per user (feed configs, bookmarks, read state, tags, user config). No blobs. Infrastructure cost per user is negligible. | |
| 18 | + | ||
| 19 | + | | Plan | Price | Stripe fees | Net to MNW | Effective monthly | | |
| 20 | + | |------|-------|-------------|------------|-------------------| | |
| 21 | + | | Monthly | $1/mo | ~$0.33/mo | ~$0.67/mo | $0.67 | | |
| 22 | + | | Annual | $8/yr | ~$0.53/yr | ~$7.47/yr | $0.62 | | |
| 23 | + | ||
| 24 | + | Annual pricing exists because payment processing fees on small monthly charges are disproportionate. This is stated openly. | |
| 25 | + | ||
| 26 | + | **What's included:** Full cloud sync across all devices — feeds, bookmarks, read state, tags, settings. Everything BB stores. | |
| 27 | + | ||
| 28 | + | ## GoingsOn | |
| 29 | + | ||
| 30 | + | **App price:** Free. | |
| 31 | + | **Sync is the only monetization.** | |
| 32 | + | ||
| 33 | + | GO syncs 14 tables (tasks, subtasks, contacts, email accounts, events, milestones, attachments, annotations, etc.). Metadata is small (1-5 MB). Some users sync email attachments as blobs, but most don't. Attachment sync is included — the few heavy users are subsidized by the majority. | |
| 34 | + | ||
| 35 | + | | Plan | Price | Stripe fees | Net to MNW | Effective monthly | | |
| 36 | + | |------|-------|-------------|------------|-------------------| | |
| 37 | + | | Monthly | $2/mo | ~$0.36/mo | ~$1.64/mo | $1.64 | | |
| 38 | + | | Annual | $15/yr | ~$0.74/yr | ~$14.26/yr | $1.19 | | |
| 39 | + | ||
| 40 | + | Higher than BB because GO is a more complex app with a larger sync surface (14 tables vs 7, blob support, more development investment). | |
| 41 | + | ||
| 42 | + | **What's included:** Full cloud sync across all devices — tasks, contacts, events, email accounts, attachments, everything GO stores. | |
| 43 | + | ||
| 44 | + | ## audiofiles | |
| 45 | + | ||
| 46 | + | **App price:** PWYW, suggested $15, floor $0. | |
| 47 | + | **Sync is the recurring revenue floor.** | |
| 48 | + | ||
| 49 | + | AF is the only app where sync costs scale meaningfully. Sample libraries can be gigabytes. The app purchase (when paid) covers development value. Sync pricing covers infrastructure. | |
| 50 | + | ||
| 51 | + | **Metadata sync is free.** Sample metadata, analysis data, VFS structure, collections, tags, edit history — all synced at no cost. This makes AF useful across devices even without paying for sync. | |
| 52 | + | ||
| 53 | + | **Blob sync (sample files) is tiered by storage:** | |
| 54 | + | ||
| 55 | + | | Tier | Storage | Monthly | Annual | Infra cost | Margin | | |
| 56 | + | |------|---------|---------|--------|------------|--------| | |
| 57 | + | | Light | 10 GB | $1/mo | $10/yr | ~$0.17/mo | ~83% | | |
| 58 | + | | Standard | 50 GB | $3/mo | $30/yr | ~$0.85/mo | ~72% | | |
| 59 | + | | Large | 200 GB | $8/mo | $80/yr | ~$3.40/mo | ~58% | | |
| 60 | + | ||
| 61 | + | Margins are intentionally modest — AF sync is near-cost, not a profit center. The PWYW app purchase is the primary revenue event. | |
| 62 | + | ||
| 63 | + | Blob sync activates per-VFS via the `sync_files` flag. Users control exactly which folders sync samples and which sync metadata only. | |
| 64 | + | ||
| 65 | + | **What's included in each tier:** Storage allocation for synced sample files. When storage is full, new blob uploads are rejected but metadata sync continues. Upgrade tier to increase capacity. | |
| 66 | + | ||
| 67 | + | ## Stripe Fee Context | |
| 68 | + | ||
| 69 | + | Why annual pricing is preferred, stated publicly: | |
| 70 | + | ||
| 71 | + | > We prefer annual billing because payment processing fees on small monthly charges are disproportionate. On a $1/month charge, Stripe takes ~33%. On a $12/year charge, Stripe takes ~5%. Annual pricing passes that savings to you. | |
| 72 | + | ||
| 73 | + | This is consistent with MNW's transparency principles. We don't hide why annual is cheaper — we explain it. | |
| 74 | + | ||
| 75 | + | ## Relationship to MNW Creator Tiers | |
| 76 | + | ||
| 77 | + | None. SyncKit is a separate product marketed at developers. App sync pricing is independent of MNW creator subscriptions. A creator paying $30/mo for Big Files still pays separately for GO/BB/AF sync like any other user. | |
| 78 | + | ||
| 79 | + | MNW may eventually offer creators a cloud storage budget as part of their tier (for project files, assets, etc.), but that would be a separate MNW feature, not SyncKit. | |
| 80 | + | ||
| 81 | + | ## Implementation | |
| 82 | + | ||
| 83 | + | - [ ] Stripe products and prices for BB sync (monthly + annual) | |
| 84 | + | - [ ] Stripe products and prices for GO sync (monthly + annual) | |
| 85 | + | - [ ] Stripe products and prices for AF blob tiers (monthly + annual, 3 tiers) | |
| 86 | + | - [ ] Sync gate in BB: check subscription status before enabling sync | |
| 87 | + | - [ ] Sync gate in GO: check subscription status before enabling sync | |
| 88 | + | - [ ] Sync gate in AF: metadata sync ungated, blob sync checks tier subscription | |
| 89 | + | - [ ] Annual renewal handling (Stripe webhook) | |
| 90 | + | - [ ] Upgrade/downgrade flow for AF tiers | |
| 91 | + | - [ ] Cancellation: sync stops at end of billing period, data retained 30 days |
| @@ -33,39 +33,57 @@ Free also attracts users who don't value the service, which creates support burd | |||
| 33 | 33 | ||
| 34 | 34 | ### Earn-Back Credit Program | |
| 35 | 35 | ||
| 36 | - | If a creator earns less on the platform than they paid in subscription fees during a 12-month period, the difference is credited as free months for the following year, capped at 12 months. | |
| 36 | + | *Planned — not yet implemented. No database schema, no code. Ship before leaving beta.* | |
| 37 | + | ||
| 38 | + | If a creator earns less on the platform than they paid in subscription fees during a 12-month period, the difference would be credited as free months for the following year, capped at 12 months. | |
| 37 | 39 | ||
| 38 | 40 | - "Earned" means gross sales through the platform vs subscription fees paid | |
| 39 | - | - Credits are calculated annually on the creator's account anniversary | |
| 40 | - | - If you don't earn back what you paid, we credit you toward next year | |
| 41 | + | - Credits calculated annually on the creator's account anniversary | |
| 42 | + | - If you don't earn back what you paid, credit toward next year | |
| 41 | 43 | ||
| 42 | - | A creator who pays $120 in Basic tier fees over a year but only earns $60 in sales gets 6 months free the following year. A creator who earns nothing gets the full 12 months free. A creator who earns $120 or more gets no credit — because the platform already paid for itself. | |
| 44 | + | A creator who pays $120 in Basic tier fees over a year but only earns $60 in sales would get 6 months free the following year. A creator who earns nothing would get the full 12 months free. A creator who earns $120 or more gets no credit — because the platform already paid for itself. | |
| 43 | 45 | ||
| 44 | 46 | ### Paid Add-Ons | |
| 45 | 47 | ||
| 46 | 48 | Base tiers include all platform software features. Some capabilities with real marginal costs are available as monthly add-ons: | |
| 47 | 49 | ||
| 48 | - | - **SyncKit cloud sync** — infrastructure-as-a-service for indie developers | |
| 50 | + | - **SyncKit cloud sync** — E2E encrypted sync for indie developers. Simple mode (pick storage, fixed 5x burst ratio) or Builder mode (configure storage + transfer independently). Application-based access, no free tier. See [synckit_pricing.md](../../synckit_pricing.md). | |
| 49 | 51 | - **Automated email via Postmark** — transactional and broadcast email | |
| 50 | 52 | - **DSP distribution** — push music to Spotify, Apple Music, etc. | |
| 51 | 53 | ||
| 52 | 54 | Add-ons pass through genuine infrastructure costs, not feature gating. | |
| 53 | 55 | ||
| 56 | + | ### App Sync Revenue | |
| 57 | + | ||
| 58 | + | The three desktop apps (GoingsOn, Balanced Breakfast, audiofiles) generate independent recurring revenue through SyncKit cloud sync subscriptions. These are separate from creator platform subscriptions — different users, different acquisition funnels. | |
| 59 | + | ||
| 60 | + | | App | Price | Net to MNW/mo | Infra Cost | Margin | | |
| 61 | + | |-----|-------|---------------|------------|--------| | |
| 62 | + | | GoingsOn | $2/mo or $15/yr | $1.19-1.64 | Negligible (metadata, 1-5 MB) | ~80%+ | | |
| 63 | + | | Balanced Breakfast | $1/mo or $8/yr | $0.62-0.67 | Negligible (~1 MB) | ~90%+ | | |
| 64 | + | | audiofiles | $1-8/mo (tiered by storage) | $0.57-4.60 | $0.17-3.40 (S3 blob storage) | 58-83% | | |
| 65 | + | ||
| 66 | + | App sync runs on the same SyncKit infrastructure that already exists for the creator platform. Marginal cost per app user is near zero for metadata-only apps (GO, BB). audiofiles is the exception — blob storage for sample files has real per-user cost. | |
| 67 | + | ||
| 68 | + | These streams lower the creator count needed for break-even. At moderate adoption (~200 GO, ~100 BB, ~50 AF users), app sync covers the full ~$600/mo infrastructure cost. Creator subscriptions then become pure margin. | |
| 69 | + | ||
| 70 | + | See [app_sync_pricing.md](./app_sync_pricing.md) for detailed pricing and [financial_dashboard.md](./financial_dashboard.md) for adoption scenarios and combined break-even analysis. | |
| 71 | + | ||
| 54 | 72 | --- | |
| 55 | 73 | ||
| 56 | 74 | ## Cost Structure | |
| 57 | 75 | ||
| 58 | 76 | ### Fixed Costs (Monthly) | |
| 59 | 77 | ||
| 60 | - | | Category | Low | High | Notes | | |
| 61 | - | |----------|-----|------|-------| | |
| 62 | - | | Infrastructure | $135 | $550 | App servers, database, Redis, object storage, load balancer | | |
| 63 | - | | Operations | $47 | $215 | Domains, SSL, DNS, monitoring, security scanning, logs | | |
| 64 | - | | Business | $220 | $580 | Payment processing, accounting, legal reserve, insurance, compliance | | |
| 65 | - | | Development | $0 | $100 | Git hosting, CI/CD, dev environments | | |
| 66 | - | | **Total Fixed** | **$402** | **$1,445** | | | |
| 78 | + | | Category | Actual | Budgeted | Notes | | |
| 79 | + | |----------|--------|----------|-------| | |
| 80 | + | | Infrastructure (Hetzner) | $31 | $31 | VPS, object storage, backups, volumes, IPv4 | | |
| 81 | + | | Operations | ~$5 | $45–80 | Domains, Cloudflare (free now, Pro budgeted), Postmark | | |
| 82 | + | | Business | ~$337 | $834–1,114 | Coworking (Irvine $332), compliance; budgeted adds Boulder, legal reserve, insurance | | |
| 83 | + | | Development | $200 | $200 | Claude Code | | |
| 84 | + | | **Total Fixed** | **~$573** | **$1,110–1,425** | | | |
| 67 | 85 | ||
| 68 | - | **Current actual: ~$600/month** at minimal scale. | |
| 86 | + | **Current actual: ~$573/month.** Budgeted includes services not yet active (Boulder coworking, Cloudflare Pro, Postmark, legal reserve, insurance). | |
| 69 | 87 | ||
| 70 | 88 | See [tech_costs.md](../strategy/tech_costs.md) for line-item detail within each category. | |
| 71 | 89 | ||
| @@ -86,26 +104,35 @@ Ranges reflect variability in upload frequency, audience size, and content type. | |||
| 86 | 104 | ||
| 87 | 105 | ## Break-Even Analysis | |
| 88 | 106 | ||
| 89 | - | To cover ~$600/month fixed costs: | |
| 107 | + | At current actual costs (~$573/mo): | |
| 108 | + | ||
| 109 | + | | Tier Mix | Avg Margin | Creators Needed | | |
| 110 | + | |----------|------------|-----------------| | |
| 111 | + | | Basic-heavy | ~$8.50 | ~67 | | |
| 112 | + | | Audio-heavy | ~$17.00 | ~34 | | |
| 113 | + | | Video-heavy | ~$24.00 | ~24 | | |
| 114 | + | | Mixed | ~$19.00 | ~30 | | |
| 115 | + | ||
| 116 | + | At budgeted costs (~$1,200/mo): | |
| 90 | 117 | ||
| 91 | 118 | | Tier Mix | Avg Margin | Creators Needed | | |
| 92 | 119 | |----------|------------|-----------------| | |
| 93 | - | | Basic-heavy | ~$8.50 | ~70 | | |
| 94 | - | | Audio-heavy | ~$17.00 | ~35 | | |
| 95 | - | | Video-heavy | ~$24.00 | ~25 | | |
| 96 | - | | Mixed | ~$19.00 | ~32 | | |
| 120 | + | | Basic-heavy | ~$8.50 | ~141 | | |
| 121 | + | | Audio-heavy | ~$17.00 | ~71 | | |
| 122 | + | | Video-heavy | ~$24.00 | ~50 | | |
| 123 | + | | Mixed | ~$19.00 | ~63 | | |
| 97 | 124 | ||
| 98 | - | **Survival threshold: 25--70 paying creators** depending on tier mix. ~32 for a realistic mixed-tier distribution. | |
| 125 | + | **Survival threshold: 24--141 paying creators** depending on tier mix and cost scenario. At current actual costs, ~30 for a realistic mixed-tier distribution. | |
| 99 | 126 | ||
| 100 | 127 | ### Sustainable Operation | |
| 101 | 128 | ||
| 102 | - | To cover costs plus $1,000/month for ongoing development, support, and reserves: | |
| 129 | + | To cover budgeted costs (~$1,200/mo) plus surplus: | |
| 103 | 130 | ||
| 104 | 131 | | Target monthly surplus | Creators needed (mixed) | | |
| 105 | 132 | |------------------------|-------------------------| | |
| 106 | - | | $1,000 | ~85 | | |
| 107 | - | | $2,000 | ~137 | | |
| 108 | - | | $3,000 | ~190 | | |
| 133 | + | | $1,000 | ~116 | | |
| 134 | + | | $2,000 | ~168 | | |
| 135 | + | | $3,000 | ~221 | | |
| 109 | 136 | ||
| 110 | 137 | ### Comfortable Operation | |
| 111 | 138 | ||
| @@ -113,9 +140,9 @@ To provide meaningful income (~$5,000/month after costs): | |||
| 113 | 140 | ||
| 114 | 141 | | At average margin of... | Creators needed | | |
| 115 | 142 | |-------------------------|-----------------| | |
| 116 | - | | $17 (audio-heavy) | ~330 | | |
| 117 | - | | $24 (video-heavy) | ~235 | | |
| 118 | - | | $19 (mixed) | ~295 | | |
| 143 | + | | $17 (audio-heavy) | ~365 | | |
| 144 | + | | $24 (video-heavy) | ~258 | | |
| 145 | + | | $19 (mixed) | ~326 | | |
| 119 | 146 | ||
| 120 | 147 | --- | |
| 121 | 148 | ||
| @@ -240,3 +267,5 @@ This isn't a pitch deck. It's an honest accounting of where we are. | |||
| 240 | 267 | - [tech_costs.md](../strategy/tech_costs.md) — line-item detail, projections, unknowns | |
| 241 | 268 | - [How We Work](../../public/about/how-we-work.md) — why we're structured this way | |
| 242 | 269 | - [Payment Independence](./payment-independence.md) — our approach to payment processing | |
| 270 | + | - [App Sync Pricing](./app_sync_pricing.md) — GO, BB, AF sync pricing and margins | |
| 271 | + | - [SyncKit Pricing](./synckit_pricing.md) — B2B SDK pricing model |
| @@ -0,0 +1,62 @@ | |||
| 1 | + | # Expense Ledger | |
| 2 | + | ||
| 3 | + | Actual business expenses for Make Creative, LLC. Updated as expenses are incurred. | |
| 4 | + | ||
| 5 | + | ## Recurring Monthly | |
| 6 | + | ||
| 7 | + | | Expense | Vendor | Amount | Start Date | Term | Notes | | |
| 8 | + | |---------|--------|--------|------------|------|-------| | |
| 9 | + | | Hetzner (all infra) | Hetzner | $31.00/mo | — | Monthly | CCX13 prod ($14.00), 2x CPX11 CI ($5.96), backups ($2.80), S3 ($5.99), volumes ($0.90), IPv4 ($1.35). Invoice 081000817566 (March 2026). | | |
| 10 | + | | Coworking (Irvine) | Industrious | $332.00/mo | 2026-05-01 | Month-to-month | Access membership, 24/7, 3 meeting room hrs/mo, mailbox. 3333 Michelson Dr, Suite 300, Irvine CA 92612. | | |
| 11 | + | | Claude Code | Anthropic | $200.00/mo | — | Monthly | Max plan. Primary development tool. | | |
| 12 | + | | Domain registrations | Various | ~$5/mo | — | Annual (amortized) | makenot.work + others | | |
| 13 | + | | Cloudflare | Cloudflare | $0/mo | — | — | Free plan. Budget $25/mo for Pro when needed. | | |
| 14 | + | | Postmark | Postmark | ~$0/mo | — | — | Minimal usage. Budget $15-50/mo for growth. | | |
| 15 | + | ||
| 16 | + | ### Founder Salary | |
| 17 | + | ||
| 18 | + | | Period | Monthly | Annual | | |
| 19 | + | |--------|---------|--------| | |
| 20 | + | | Months 1-12 | $3,000 | $36,000 | | |
| 21 | + | | Month 13+ | $5,000 | $60,000 | | |
| 22 | + | ||
| 23 | + | Year 2 upgrade contingent on revenue growth. If revenue has not materialized by month 13, additional funding or cost reduction needed. | |
| 24 | + | ||
| 25 | + | **Not business expenses:** Sourcehut ($10/mo, personal). | |
| 26 | + | ||
| 27 | + | ### Monthly totals | |
| 28 | + | ||
| 29 | + | | Scenario | Ops Only | + $3K Salary | + $5K Salary | | |
| 30 | + | |----------|---------|-------------|-------------| | |
| 31 | + | | **Current actual** | **~$573** | **~$3,573** | **~$5,573** | | |
| 32 | + | | + Cloudflare Pro | ~$598 | ~$3,598 | ~$5,598 | | |
| 33 | + | | + Boulder coworking | ~$930 | ~$3,930 | ~$5,930 | | |
| 34 | + | | + Postmark growth ($50) | ~$980 | ~$3,980 | ~$5,980 | | |
| 35 | + | | Full budgeted (all + legal/insurance) | ~$1,110–1,425 | ~$4,110–4,425 | ~$6,110–6,425 | | |
| 36 | + | ||
| 37 | + | ## One-Time / Completed | |
| 38 | + | ||
| 39 | + | | Expense | Amount | Date | Notes | | |
| 40 | + | |---------|--------|------|-------| | |
| 41 | + | | LLC formation (CO) | — | 2026 | Make Creative, LLC | | |
| 42 | + | | Launch expenses (misc) | ~$2,000 | 2026-02 to 2026-04 | Infrastructure, domains, initial setup | | |
| 43 | + | ||
| 44 | + | ## Expense Categories for Tax | |
| 45 | + | ||
| 46 | + | | Category | IRS Deduction | Expenses | | |
| 47 | + | |----------|---------------|----------| | |
| 48 | + | | Salary / guaranteed payments | Schedule C, Line 26 (Wages) or SE income | Founder salary (depends on LLC tax election) | | |
| 49 | + | | Office / coworking | Schedule C, Line 20b (Rent) | Industrious memberships | | |
| 50 | + | | Web hosting / infrastructure | Schedule C, Line 27a (Other expenses) | Hetzner, domains, Cloudflare | | |
| 51 | + | | Software / tools | Schedule C, Line 27a | Claude Code, dev tools | | |
| 52 | + | | Communications / email | Schedule C, Line 27a | Postmark | | |
| 53 | + | | Legal / compliance | Schedule C, Line 17 | LLC filing, legal counsel | | |
| 54 | + | | Travel | Schedule C, Line 24a | Events, conferences | | |
| 55 | + | ||
| 56 | + | ## Notes | |
| 57 | + | ||
| 58 | + | - Industrious is a license agreement, not a lease — classified as rent/office expense for tax purposes. | |
| 59 | + | - Month-to-month terms: 1 calendar month non-renewal notice required. | |
| 60 | + | - Auto-renews unless cancelled. Price adjustments capped at 10% with 80 days notice. | |
| 61 | + | - No security deposit on current agreement. | |
| 62 | + | - Meeting room hours (3/mo included) are useful for creator pitches, investor meetings, and partner calls. |
| @@ -40,6 +40,24 @@ It expires. No rollover. This is a feature, not a bug — it creates gentle urge | |||
| 40 | 40 | ||
| 41 | 41 | ## Perks | |
| 42 | 42 | ||
| 43 | + | ### Forum features (Multithreaded) | |
| 44 | + | ||
| 45 | + | Fan+ unlocks storage-heavy forum capabilities: | |
| 46 | + | ||
| 47 | + | - **Signatures** — text + image, rendered on every post | |
| 48 | + | - **Custom / larger profile images** — beyond the default generated avatar | |
| 49 | + | - **Image and video embeds in posts** — inline media in thread replies | |
| 50 | + | - **Private community access** — Fan+-gated communities (e.g., MNW development community) | |
| 51 | + | ||
| 52 | + | Free accounts can read everything, post text, search, endorse, and track threads. The free experience is fully functional for discussion — Fan+ adds rich media participation. | |
| 53 | + | ||
| 54 | + | **Creator exception:** Creators automatically receive all Fan+ forum perks in their own communities at no additional cost. They already pay $10-60/mo for the platform. The only Fan+-exclusive perk creators do not receive is the + badge — that signals "I'm a fan who pays," not "I'm a creator." | |
| 55 | + | ||
| 56 | + | This gating serves three purposes: | |
| 57 | + | 1. Storage-expensive features (signatures rendered on every post, inline media) are funded by the people using them | |
| 58 | + | 2. Paying users have skin in the game, reducing spam and low-effort posting | |
| 59 | + | 3. Creators can showcase the upgraded experience in their own communities, creating a natural upsell | |
| 60 | + | ||
| 43 | 61 | ### `+` badge | |
| 44 | 62 | ||
| 45 | 63 | A `+` appears after the subscriber's username in every social context: | |
| @@ -73,7 +91,7 @@ The community is valuable because: | |||
| 73 | 91 | ||
| 74 | 92 | ## What Fan+ is NOT | |
| 75 | 93 | ||
| 76 | - | - **Not feature gating.** Every platform feature is available to free users. Wishlist, collections, gifting, export, follows, feed, library — all free. Fan+ does not unlock functionality. | |
| 94 | + | - **Not core feature gating.** Every core platform feature is available to free users. Wishlist, collections, gifting, export, follows, feed, library, forum reading and text posting — all free. Fan+ unlocks rich media participation in forums, not access to the platform itself. | |
| 77 | 95 | - **Not ad removal.** MNW has no ads. | |
| 78 | 96 | - **Not priority support.** One person runs the platform. Promising tiers of support is dishonest. | |
| 79 | 97 | - **Not early access.** Features ship to everyone at the same time. Promising early access creates resentment and is hard to deliver consistently. | |
| @@ -163,6 +181,8 @@ On each successful billing cycle: | |||
| 163 | 181 | ||
| 164 | 182 | - [ ] Decide: reuse existing subscription infra or build Fan+-specific tables | |
| 165 | 183 | - [ ] Implement Fan+ access gating in Multithreaded (private community, subscription check) | |
| 184 | + | - [ ] Implement Fan+ forum feature gates (signatures, custom images, image/video embeds) | |
| 185 | + | - [ ] Implement creator auto-grant of Fan+ forum perks in own communities (no + badge) | |
| 166 | 186 | - [ ] Write guarantees page copy | |
| 167 | 187 | - [ ] Write economics page copy | |
| 168 | 188 | - [ ] Design email template for monthly credit delivery |
| @@ -1,18 +1,40 @@ | |||
| 1 | 1 | # Financial Dashboard | |
| 2 | 2 | ||
| 3 | - | Current burn: ~$600/mo. Revenue: $0 (pre-launch). Break-even: ~36 creators (mixed tiers, corrected). Year 1 total: ~$30-57K. | |
| 3 | + | Current burn: ~$3,573/mo (actual ops + $3K salary). Budgeted: ~$4,200-4,425/mo. Revenue: soft launch (2026-04-13), tracking toward first paying creators. Break-even (salary + ops): ~188 creators (actual) / ~232 (budgeted). Funding: $240K. Runway: 4.4-5.6 years. | |
| 4 | 4 | ||
| 5 | 5 | ## Funding | |
| 6 | 6 | ||
| 7 | - | Total committed: $170,000. Total reserve: $50,000. Total available: $220,000. | |
| 7 | + | Total committed: $190,000. Total reserve: $50,000. Total available: $240,000. | |
| 8 | 8 | ||
| 9 | 9 | | Source | Amount | Type | Conditions | | |
| 10 | 10 | |--------|--------|------|------------| | |
| 11 | 11 | | Personal savings | $20,000 | Self-funded | None | | |
| 12 | + | | Personal funds (additional) | $20,000 | Self-funded | None | | |
| 12 | 13 | | Family (parents) | $150,000 | Gift/loan | No strings | | |
| 13 | 14 | | Family (parents) — reserve | $50,000 | Gift/loan | No strings, draw on request | | |
| 14 | 15 | ||
| 15 | - | No equity given, no investor obligations, no reporting requirements, no board seats. No repayment schedule. Reserve is separate from the $170K commitment. | |
| 16 | + | No equity given, no investor obligations, no reporting requirements, no board seats. No repayment schedule. Reserve is separate from the $190K commitment. | |
| 17 | + | ||
| 18 | + | ### Founder Salary | |
| 19 | + | ||
| 20 | + | | Period | Monthly | Annual | Notes | | |
| 21 | + | |--------|---------|--------|-------| | |
| 22 | + | | Months 1-12 | $3,000 | $36,000 | Initial rate | | |
| 23 | + | | Month 13+ | $5,000 | $60,000 | Upgrade contingent on growth; may require additional funding if revenue has not materialized | | |
| 24 | + | ||
| 25 | + | Salary is a business expense (Schedule C or W-2 from LLC, depending on tax election). Included in burn rate calculations below. | |
| 26 | + | ||
| 27 | + | ### Burn Rate & Runway | |
| 28 | + | ||
| 29 | + | | Scenario | Monthly Burn | Committed Runway | With Reserve | | |
| 30 | + | |----------|-------------|------------------|--------------| | |
| 31 | + | | Actual (ops + $3K salary) | ~$3,573 | **4.4 years** | **5.6 years** | | |
| 32 | + | | Budgeted (ops + $3K salary) | ~$4,200-4,425 | **3.6-3.8 years** | **4.5-4.8 years** | | |
| 33 | + | | Year 2+ (ops + $5K salary) | ~$5,573-6,425 | — | — | | |
| 34 | + | ||
| 35 | + | **Actual spend to date: ~$2,000** (launch expenses, 3 months of development). At the Year 1 burn rate (~$3,573/mo actual), committed funding covers **4.4 years**. With reserve: **5.6 years**. | |
| 36 | + | ||
| 37 | + | Year 2 salary upgrade to $5K/mo adds ~$24K/yr. If revenue has not grown to offset this by month 13, additional funding or cost reduction is needed. At $5K salary + full budgeted ops (~$6,425/mo), runway shortens to ~2.5 years committed — still substantial but no longer indefinite. This is the velocity incentive: growth before month 13 determines whether the salary upgrade is self-funding. | |
| 16 | 38 | ||
| 17 | 39 | --- | |
| 18 | 40 | ||
| @@ -22,13 +44,13 @@ Source: `docs/internal/strategy/tech_costs.md`, `docs/internal/business/economic | |||
| 22 | 44 | ||
| 23 | 45 | | Category | Low | High | Current Actual | | |
| 24 | 46 | |----------|-----|------|----------------| | |
| 25 | - | | Infrastructure | $135 | $550 | — | | |
| 26 | - | | Operations | $47 | $215 | — | | |
| 27 | - | | Business | $220 | $580 | — | | |
| 28 | - | | Development | $0 | $100 | — | | |
| 29 | - | | **Total Fixed** | **$402** | **$1,445** | **~$600** | | |
| 47 | + | | Infrastructure (Hetzner) | $31 | $31 | $31 | | |
| 48 | + | | Operations | $45 | $80 | ~$5 | | |
| 49 | + | | Business | $834 | $1,114 | ~$337 | | |
| 50 | + | | Development | $200 | $200 | $200 | | |
| 51 | + | | **Total Fixed** | **$1,110** | **$1,425** | **~$573** | | |
| 30 | 52 | ||
| 31 | - | Range includes costs not yet active (insurance, paid monitoring, legal reserve at full rate). Current actual reflects minimal-scale operation. | |
| 53 | + | Source: Hetzner invoice 081000817566 (March 2026, $31.00). Current actual is all services billed today. Budgeted range includes Cloudflare Pro ($25), Postmark growth ($15-50), Boulder coworking (~$332), legal reserve ($100-300), and business insurance ($50-100) — expected but not yet active. See `tech_costs.md` for line-item detail. | |
| 32 | 54 | ||
| 33 | 55 | --- | |
| 34 | 56 | ||
| @@ -60,20 +82,114 @@ Source: `docs/internal/business/fan-plus.md` | |||
| 60 | 82 | ||
| 61 | 83 | At scale: 100 subs = ~$272/mo, 500 subs = ~$1,360/mo, 1,000 subs = ~$2,720/mo. | |
| 62 | 84 | ||
| 85 | + | ### App Sync Revenue | |
| 86 | + | ||
| 87 | + | Source: `docs/internal/business/app_sync_pricing.md` | |
| 88 | + | ||
| 89 | + | Desktop apps (GoingsOn, Balanced Breakfast, audiofiles) monetize through SyncKit cloud sync subscriptions. These users are independent of the creator platform — separate acquisition funnels, separate revenue. | |
| 90 | + | ||
| 91 | + | | App | Monthly | Annual | Net/mo (monthly) | Net/mo (annual) | Infra Cost | Margin | | |
| 92 | + | |-----|---------|--------|-------------------|-----------------|------------|--------| | |
| 93 | + | | GoingsOn | $2/mo | $15/yr | ~$1.64 | ~$1.19 | Negligible | ~80%+ | | |
| 94 | + | | Balanced Breakfast | $1/mo | $8/yr | ~$0.67 | ~$0.62 | Negligible | ~90%+ | | |
| 95 | + | | audiofiles (avg) | ~$3/mo | ~$30/yr | ~$2.57 | ~$2.38 | $0.17-3.40 | 58-83% | | |
| 96 | + | ||
| 97 | + | Annual billing is preferred — Stripe fees are disproportionate on small monthly charges (33% on $1/mo vs ~5% on $12/yr). | |
| 98 | + | ||
| 99 | + | #### Adoption Scenarios | |
| 100 | + | ||
| 101 | + | | Scenario | Timeline | GO users | BB users | AF users (avg $3/mo) | Monthly app revenue | | |
| 102 | + | |----------|----------|----------|----------|----------------------|---------------------| | |
| 103 | + | | Conservative | 6 mo | 50 | 30 | 20 | ~$150 | | |
| 104 | + | | Moderate | 12 mo | 200 | 100 | 50 | ~$620 | | |
| 105 | + | | Optimistic | 18 mo | 500 | 300 | 150 | ~$1,650 | | |
| 106 | + | ||
| 107 | + | GoingsOn is the most likely early driver — productivity apps have higher willingness to pay for sync than feed readers. audiofiles has the highest per-user revenue but the smallest addressable market. | |
| 108 | + | ||
| 109 | + | ### SyncKit SDK (B2B, Future) | |
| 110 | + | ||
| 111 | + | Source: `docs/internal/business/synckit_pricing.md` | |
| 112 | + | ||
| 113 | + | Not yet productized. Revenue from indie developers using SyncKit as sync-as-a-service. Application-based access, no free tier. | |
| 114 | + | ||
| 115 | + | | Mode | Example Config | Monthly Price | | |
| 116 | + | |------|----------------|---------------| | |
| 117 | + | | Simple | 1 GB, 5x burst | $0.30 | | |
| 118 | + | | Simple | 10 GB, 5x burst | $4.50 | | |
| 119 | + | | Builder | 20 GB, 10x burst | $9.00 | | |
| 120 | + | | Builder | 200 GB, 3x burst | $48.00 | | |
| 121 | + | ||
| 122 | + | Infrastructure margin: ~95% on storage, ~67% on transfer. Not modeled in projections until productized. | |
| 123 | + | ||
| 63 | 124 | --- | |
| 64 | 125 | ||
| 65 | 126 | ## Break-Even | |
| 66 | 127 | ||
| 67 | 128 | Source: `economics.md`. No Stripe Connect fees on Standard accounts. | |
| 68 | 129 | ||
| 130 | + | #### Infrastructure-only break-even (ops costs, no salary) | |
| 131 | + | ||
| 132 | + | At current actual ops (~$573/mo): | |
| 133 | + | ||
| 69 | 134 | | Tier Mix | Avg Margin | Creators Needed | | |
| 70 | 135 | |----------|------------|-----------------| | |
| 71 | - | | Basic-heavy | ~$8.50 | **~70** | | |
| 72 | - | | Audio-heavy | ~$17.00 | **~35** | | |
| 73 | - | | Video-heavy | ~$24.00 | **~25** | | |
| 74 | - | | Mixed | ~$19.00 | **~32** | | |
| 136 | + | | Mixed | ~$19.00 | **~30** | | |
| 75 | 137 | ||
| 76 | - | Based on ~$600/mo fixed costs. Range: **25-70 creators**, ~32 for realistic mixed tier distribution. | |
| 138 | + | At budgeted ops (~$1,200/mo): | |
| 139 | + | ||
| 140 | + | | Tier Mix | Avg Margin | Creators Needed | | |
| 141 | + | |----------|------------|-----------------| | |
| 142 | + | | Mixed | ~$19.00 | **~63** | | |
| 143 | + | ||
| 144 | + | #### Full break-even (ops + $3K/mo salary) | |
| 145 | + | ||
| 146 | + | At current actual ops + salary (~$3,573/mo): | |
| 147 | + | ||
| 148 | + | | Tier Mix | Avg Margin | Creators Needed | | |
| 149 | + | |----------|------------|-----------------| | |
| 150 | + | | Basic-heavy | ~$8.50 | **~420** | | |
| 151 | + | | Audio-heavy | ~$17.00 | **~210** | | |
| 152 | + | | Video-heavy | ~$24.00 | **~149** | | |
| 153 | + | | Mixed | ~$19.00 | **~188** | | |
| 154 | + | ||
| 155 | + | At budgeted ops + salary (~$4,200/mo): | |
| 156 | + | ||
| 157 | + | | Tier Mix | Avg Margin | Creators Needed | | |
| 158 | + | |----------|------------|-----------------| | |
| 159 | + | | Basic-heavy | ~$8.50 | **~494** | | |
| 160 | + | | Audio-heavy | ~$17.00 | **~247** | | |
| 161 | + | | Video-heavy | ~$24.00 | **~175** | | |
| 162 | + | | Mixed | ~$19.00 | **~221** | | |
| 163 | + | ||
| 164 | + | Infrastructure break-even is easy (~30-63 creators). Full self-sustaining (salary-inclusive) requires ~188-221 creators at mixed tiers — achievable but requires real traction. | |
| 165 | + | ||
| 166 | + | ### Combined Break-Even (Creator Subs + App Sync) | |
| 167 | + | ||
| 168 | + | App sync revenue offsets fixed infrastructure costs, reducing the creator count needed for break-even. | |
| 169 | + | ||
| 170 | + | Using budgeted ops + $3K salary (~$4,200/mo total): | |
| 171 | + | ||
| 172 | + | | App Sync Scenario | App Revenue | Remaining to Cover | Creators Needed (mixed) | | |
| 173 | + | |-------------------|-------------|---------------------|-------------------------| | |
| 174 | + | | None | $0 | ~$4,200 | ~221 | | |
| 175 | + | | Conservative ($150/mo) | ~$150 | ~$4,050 | ~213 | | |
| 176 | + | | Moderate ($620/mo) | ~$620 | ~$3,580 | ~188 | | |
| 177 | + | | Optimistic ($1,650/mo) | ~$1,650 | ~$2,550 | ~134 | | |
| 178 | + | ||
| 179 | + | App sync revenue helps but doesn't transform the picture when salary is included. The real leverage is creator subscriptions — each mixed-tier creator contributes ~$19/mo margin. | |
| 180 | + | ||
| 181 | + | ### Impact on Sustainable / Comfortable Operation | |
| 182 | + | ||
| 183 | + | Using budgeted ops (~$1,200/mo), salary included as target: | |
| 184 | + | ||
| 185 | + | | Target | Creators (subs only) | Creators (with moderate app sync) | | |
| 186 | + | |--------|----------------------|-----------------------------------| | |
| 187 | + | | Ops break-even (no salary) | ~63 | ~31 | | |
| 188 | + | | Ops + $3K salary (Year 1) | ~221 | ~188 | | |
| 189 | + | | Ops + $5K salary (Year 2+) | ~326 | ~294 | | |
| 190 | + | | Ops + $5K + $1K reserve | ~379 | ~346 | | |
| 191 | + | ||
| 192 | + | The Year 2 salary upgrade is the key growth gate. If ~220+ creators are paying by month 13, the $5K salary is self-funding. If not, it draws from reserves — sustainable for ~2.5 years but signals the need for faster growth or cost adjustment. | |
| 77 | 193 | ||
| 78 | 194 | --- | |
| 79 | 195 | ||
| @@ -81,35 +197,37 @@ Based on ~$600/mo fixed costs. Range: **25-70 creators**, ~32 for realistic mixe | |||
| 81 | 197 | ||
| 82 | 198 | Source: `docs/internal/strategy/tech_costs.md` (Cost Projections section) | |
| 83 | 199 | ||
| 200 | + | Using budgeted costs (~$1,200/mo baseline): | |
| 201 | + | ||
| 84 | 202 | ### At 100 Creators (Mixed Tiers) | |
| 85 | 203 | ||
| 86 | 204 | | Line | Amount | | |
| 87 | 205 | |------|--------| | |
| 88 | - | | Fixed costs | ~$600 | | |
| 206 | + | | Fixed costs | ~$1,200 | | |
| 89 | 207 | | Variable costs (~$3 avg) | ~$300 | | |
| 90 | - | | **Total costs** | **~$900** | | |
| 208 | + | | **Total costs** | **~$1,500** | | |
| 91 | 209 | | Revenue (~$24 avg) | ~$2,400 | | |
| 92 | - | | **Surplus** | **~$1,500** | | |
| 210 | + | | **Surplus** | **~$900** | | |
| 93 | 211 | ||
| 94 | 212 | ### At 500 Creators | |
| 95 | 213 | ||
| 96 | 214 | | Line | Amount | | |
| 97 | 215 | |------|--------| | |
| 98 | - | | Fixed costs | ~$800 | | |
| 216 | + | | Fixed costs | ~$1,300 | | |
| 99 | 217 | | Variable costs | ~$1,500 | | |
| 100 | - | | **Total costs** | **~$2,300** | | |
| 218 | + | | **Total costs** | **~$2,800** | | |
| 101 | 219 | | Revenue | ~$12,000 | | |
| 102 | - | | **Surplus** | **~$9,700** | | |
| 220 | + | | **Surplus** | **~$9,200** | | |
| 103 | 221 | ||
| 104 | 222 | ### At 2,000 Creators | |
| 105 | 223 | ||
| 106 | 224 | | Line | Amount | | |
| 107 | 225 | |------|--------| | |
| 108 | - | | Fixed costs | ~$1,500 | | |
| 226 | + | | Fixed costs | ~$1,600 | | |
| 109 | 227 | | Variable costs | ~$6,000 | | |
| 110 | - | | **Total costs** | **~$7,500** | | |
| 228 | + | | **Total costs** | **~$7,600** | | |
| 111 | 229 | | Revenue | ~$48,000 | | |
| 112 | - | | **Surplus** | **~$40,500** | | |
| 230 | + | | **Surplus** | **~$40,400** | | |
| 113 | 231 | ||
| 114 | 232 | --- | |
| 115 | 233 | ||
| @@ -149,10 +267,11 @@ Outreach expansions (newsletter sponsorships, jam sponsorships, open source spon | |||
| 149 | 267 | ||
| 150 | 268 | | Category | Low | High | | |
| 151 | 269 | |----------|-----|------| | |
| 152 | - | | Operating (12mo at ~$600) | $7,200 | $7,200 | | |
| 270 | + | | Operating (12mo) | $6,876 (actual ops) | $17,100 (budgeted ops) | | |
| 271 | + | | Founder salary (12mo at $3K) | $36,000 | $36,000 | | |
| 153 | 272 | | One-time investments | $13,259 | $26,509 | | |
| 154 | 273 | | Annual recurring | $10,046 | $22,846 | | |
| 155 | - | | **Total** | **~$30,505** | **~$56,555** | | |
| 274 | + | | **Total** | **~$66,181** | **~$102,455** | | |
| 156 | 275 | ||
| 157 | 276 | ### Comparison with `pitch.md` | |
| 158 | 277 | ||
| @@ -193,6 +312,10 @@ Projected Year 1 revenue: ~$5K. Net: -$75K (investment year). Requires securitie | |||
| 193 | 312 | - [x] `pitch.md` high-end Year 1 total arithmetic error — fixed ($49,055 → $50,055) | |
| 194 | 313 | - [x] `pitch.md` community building line missing expansion capital — added reference to `budget.md` ($1,700-6,500/yr) | |
| 195 | 314 | - [x] Stripe Connect corrected from Express to Standard — no per-account, payout-volume, or per-payout fees | |
| 315 | + | - [x] App sync revenue (GO, BB, AF) added to dashboard and economics — adoption scenarios, combined break-even, impact on sustainable operation thresholds | |
| 316 | + | - [x] SyncKit SDK B2B revenue noted as future stream — pricing model documented, not yet in projections | |
| 317 | + | - [x] Coworking expense added ($332/mo Industrious Irvine, active 2026-05-01) | |
| 318 | + | - [x] All cost tables replaced with actual line items from Hetzner invoice + real vendor costs. Speculative ranges replaced with actual/budgeted columns. Hetzner total: $31/mo (was estimated $135-550). Claude Code ($200/mo) added as development cost. Total actual: ~$573/mo. All break-even, projections, and Year 1 totals recalculated across financial_dashboard.md, economics.md, and tech_costs.md | |
| 196 | 319 | ||
| 197 | 320 | --- | |
| 198 | 321 | ||
| @@ -208,6 +331,9 @@ Projected Year 1 revenue: ~$5K. Net: -$75K (investment year). Requires securitie | |||
| 208 | 331 | | events-2026.md | `docs/internal/strategy/` | Event directory with dates, ticket prices, strategic goals | | |
| 209 | 332 | | revenue-share-crowdfunding.md | Archived — summary in `docs/mnw/todo.md` Deferred | Separate venture: revenue-share model, Reg CF, financial projections | | |
| 210 | 333 | | payment-independence.md | `docs/internal/business/` | Payment processing approach, Stripe strategy | | |
| 334 | + | | expenses.md | `docs/internal/business/` | Actual expense ledger, recurring costs, tax categories | | |
| 335 | + | | app_sync_pricing.md | `docs/internal/business/` | App sync pricing (GO, BB, AF), Stripe fee context | | |
| 336 | + | | synckit_pricing.md | `docs/internal/business/` | SyncKit SDK B2B pricing, Simple/Builder modes | | |
| 211 | 337 | | compliance.md | `docs/internal/business/` | Regulatory compliance requirements | | |
| 212 | 338 | | mtl.md | `docs/internal/business/` | Money transmitter analysis | | |
| 213 | 339 | | corporate-structure.md | Archived — summary in `docs/mnw/todo.md` Deferred | Entity structure, state registration | | |
| @@ -222,3 +348,6 @@ Projected Year 1 revenue: ~$5K. Net: -$75K (investment year). Requires securitie | |||
| 222 | 348 | - Business insurance activation timeline and actual cost | |
| 223 | 349 | - 1099-K threshold changes (current: $20K + 200 transactions) | |
| 224 | 350 | - Outreach budget actual spend vs planned (track which expansions are activated) | |
| 351 | + | - App sync adoption rates by app (GO, BB, AF) — actual vs projected scenarios | |
| 352 | + | - Annual vs monthly billing ratio (annual is higher margin due to Stripe fee structure) | |
| 353 | + | - SyncKit SDK productization timeline and early developer interest |
| @@ -0,0 +1,294 @@ | |||
| 1 | + | # Partnership Targets | |
| 2 | + | ||
| 3 | + | Potential partners organized by relationship type. See [partnerships.md](./partnerships.md) for principles. | |
| 4 | + | ||
| 5 | + | ## Mutual Endorsement | |
| 6 | + | ||
| 7 | + | Organizations with near-identical values where the relationship is reciprocal visibility. We recommend them, they recommend us. | |
| 8 | + | ||
| 9 | + | ### Sourcehut | |
| 10 | + | ||
| 11 | + | Drew DeVault's source hosting. Self-funded, no VC, no tracking, sustainable pricing, builds-as-a-service. We already use it. Philosophy is almost word-for-word ours. Small enough that mutual endorsement is meaningful in both directions. | |
| 12 | + | ||
| 13 | + | Contact: Direct to Drew DeVault. | |
| 14 | + | ||
| 15 | + | ### Ghost Foundation | |
| 16 | + | ||
| 17 | + | Nonprofit (legally cannot be bought or sold). Open source publishing platform. $10M+ annual revenue, all reinvested. No ads, no VC, no shareholders. Publishes financials publicly. They take a percentage rather than flat fee, but the structural alignment is near-perfect. Large creator audience. | |
| 18 | + | ||
| 19 | + | Contact: Direct outreach. They have an integrations ecosystem worth exploring technically. | |
| 20 | + | ||
| 21 | + | ### Buttondown | |
| 22 | + | ||
| 23 | + | Bootstrapped newsletter platform. "Funded by our customers." Tracking is opt-in. Full data export. No extractive free tier. Nearly identical values language to ours. | |
| 24 | + | ||
| 25 | + | Contact: Direct to founder Justin Duke. | |
| 26 | + | ||
| 27 | + | ### Micro.blog | |
| 28 | + | ||
| 29 | + | Chronological feed, no algorithm, no ads, no follower counts, no like counts, no virality mechanics. Indie web community. Subscription model. Promotes creator-owned domains over platform lock-in. | |
| 30 | + | ||
| 31 | + | Contact: Direct to founder Manton Reece. | |
| 32 | + | ||
| 33 | + | ### Write.as | |
| 34 | + | ||
| 35 | + | Privacy-by-default publishing. No personal data collection. Open web standards (RSS, ActivityPub). Owner-operated since 2015, no exit interest. | |
| 36 | + | ||
| 37 | + | Contact: Direct to founder Matt Baer. | |
| 38 | + | ||
| 39 | + | ### Small Technology Foundation | |
| 40 | + | ||
| 41 | + | Aral Balkan's org. Rejects VC, builds "stayups not startups." Privacy-first, copyleft. Coined the "small technology" framing that describes what we're doing. Aral actively amplifies aligned projects. | |
| 42 | + | ||
| 43 | + | Contact: Direct to Aral Balkan. | |
| 44 | + | ||
| 45 | + | ### Codeberg | |
| 46 | + | ||
| 47 | + | Nonprofit community-led code hosting. No tracking, no third-party cookies. Community has voting rights. Direct alternative to GitHub's increasingly VC-adjacent model. | |
| 48 | + | ||
| 49 | + | Contact: Organizational membership. | |
| 50 | + | ||
| 51 | + | ### 37signals (Basecamp / HEY) | |
| 52 | + | ||
| 53 | + | The canonical bootstrapped, anti-VC, "calm company" tech business. Jason Fried and DHH are vocal advocates who have publicly promoted aligned companies. No formal program, but they endorse peers. | |
| 54 | + | ||
| 55 | + | Contact: Cold outreach. They've signal-boosted aligned projects before. | |
| 56 | + | ||
| 57 | + | ### itch.io | |
| 58 | + | ||
| 59 | + | Open revenue sharing (creators choose their own fee, including 0%). No approval gatekeeping. Pay-what-you-want. Ad-free. "We do not believe in exploiting content." $1B+ distributed to indie game creators. Privately held. | |
| 60 | + | ||
| 61 | + | Contact: Direct outreach. They co-sponsor indie creator events. | |
| 62 | + | ||
| 63 | + | ### Obsidian | |
| 64 | + | ||
| 65 | + | 100% user-funded, no investors. Local-first, privacy-by-default, data on your device, fully exportable. "Your thoughts belong to you." No algorithm. Large creator/writer audience with high overlap to ours. | |
| 66 | + | ||
| 67 | + | Contact: Community spotlights, direct outreach. | |
| 68 | + | ||
| 69 | + | ### Kagi | |
| 70 | + | ||
| 71 | + | Subscription-only search. No ads, no profiling, no tracking. "We answer to you." No investor pressure. Anti-algorithmic-manipulation. Same structural argument we make. | |
| 72 | + | ||
| 73 | + | Contact: Direct outreach for co-promotion. | |
| 74 | + | ||
| 75 | + | --- | |
| 76 | + | ||
| 77 | + | ## Offer Free Infrastructure | |
| 78 | + | ||
| 79 | + | Organizations doing aligned work where we could host their content, community, or distribution on MNW at no cost. Gets real usage from credible orgs, demonstrates the platform, and creates a genuine relationship. | |
| 80 | + | ||
| 81 | + | ### Oxide Computer | |
| 82 | + | ||
| 83 | + | Bryan Cantrill's company. Radical transparency, anti-lock-in, engineering-values-first. Could host community content, blog, tutorials. | |
| 84 | + | ||
| 85 | + | ### Prusa Research | |
| 86 | + | ||
| 87 | + | Bootstrapped, no investors, open source 3D printing. "Open source is our heart." Maker/creator community. Could host their maker content, guides, sample files. | |
| 88 | + | ||
| 89 | + | ### REAPER (Cockos) | |
| 90 | + | ||
| 91 | + | DRM-free perpetual-license DAW. $60 discounted/$225 commercial. No subscription extraction. Independent, bootstrapped. The anti-Adobe of audio tools. Could host tutorials, presets, user-contributed content. | |
| 92 | + | ||
| 93 | + | ### Ardour | |
| 94 | + | ||
| 95 | + | Open source DAW built by musicians. Could host community content, tutorials, templates. | |
| 96 | + | ||
| 97 | + | --- | |
| 98 | + | ||
| 99 | + | ## Formal Partner Programs | |
| 100 | + | ||
| 101 | + | Organizations with existing partnership or sponsorship programs we can apply to. | |
| 102 | + | ||
| 103 | + | ### Framework | |
| 104 | + | ||
| 105 | + | Right-to-repair laptops. Community partner program exists. "Own your hardware" maps directly onto "own your platform." Their audience (people who deliberately chose repairability over convenience) is our audience. | |
| 106 | + | ||
| 107 | + | Action: Prepare application to community partner program. | |
| 108 | + | ||
| 109 | + | ### Proton (Mail/VPN/Drive) | |
| 110 | + | ||
| 111 | + | "We can't enshittify because of how we're structured." Privacy-first, Swiss jurisdiction, open source. Has community/partner programs. | |
| 112 | + | ||
| 113 | + | Action: Prepare application. | |
| 114 | + | ||
| 115 | + | ### Nextcloud | |
| 116 | + | ||
| 117 | + | "Restore digital sovereignty." 100% open source. Full data control. Has a formal channel partner program. | |
| 118 | + | ||
| 119 | + | Action: Prepare application. | |
| 120 | + | ||
| 121 | + | ### EFF (Electronic Frontier Foundation) | |
| 122 | + | ||
| 123 | + | Digital rights, privacy, anti-surveillance. Formal Corporate Giving & Sponsorships program. Companies get an EFF Supporter badge. Current members include DuckDuckGo, Fastly, Matomo. | |
| 124 | + | ||
| 125 | + | Action: Contact partnerships team. Even a small organizational membership gets the badge and the association. | |
| 126 | + | ||
| 127 | + | ### Software Freedom Conservancy | |
| 128 | + | ||
| 129 | + | Defends copyleft, right-to-repair for software, anti-lock-in. Formal sponsor program with logo placement. Mozilla Foundation is a current sponsor. | |
| 130 | + | ||
| 131 | + | Action: Apply to sponsor program. | |
| 132 | + | ||
| 133 | + | --- | |
| 134 | + | ||
| 135 | + | ## Digital Rights and Advocacy | |
| 136 | + | ||
| 137 | + | Organizations where the relationship is closer to membership or mutual support than commercial partnership. | |
| 138 | + | ||
| 139 | + | ### Creative Commons | |
| 140 | + | ||
| 141 | + | 25 years of legal infrastructure for creator rights. "Connective tissue of the open ecosystem." Champions attribution and creator control. | |
| 142 | + | ||
| 143 | + | Contact: Open Infrastructure Circle donor program. | |
| 144 | + | ||
| 145 | + | ### Internet Archive | |
| 146 | + | ||
| 147 | + | Digital preservation, open access, anti-lock-in. Active Mastodon sponsor. Mission aligns with our data sovereignty stance. | |
| 148 | + | ||
| 149 | + | Contact: Organizational supporter program. | |
| 150 | + | ||
| 151 | + | ### FSFE (Free Software Foundation Europe) | |
| 152 | + | ||
| 153 | + | More pragmatic than FSF-US. "Public Money, Public Code" campaign. Data sovereignty focus. Has a Fellows and Supporter program for organizations. | |
| 154 | + | ||
| 155 | + | ### iFixit | |
| 156 | + | ||
| 157 | + | Right-to-repair advocacy and parts. "Repair changes the world." Same ownership philosophy we apply to data and platforms. Kyle Wiens (CEO) is vocal and media-savvy. | |
| 158 | + | ||
| 159 | + | Contact: Direct to Kyle Wiens. They co-market with aligned brands. | |
| 160 | + | ||
| 161 | + | --- | |
| 162 | + | ||
| 163 | + | ## Privacy-Aligned Tech | |
| 164 | + | ||
| 165 | + | Companies whose privacy-first positioning creates natural audience overlap. | |
| 166 | + | ||
| 167 | + | ### Mullvad | |
| 168 | + | ||
| 169 | + | No accounts, no email required. Hardcore privacy. Their users are the people who read our source code before signing up. | |
| 170 | + | ||
| 171 | + | ### Tuta (formerly Tutanota) | |
| 172 | + | ||
| 173 | + | Open source encrypted email. No ads, no tracking, renewable energy. Protects journalists and whistleblowers. Independent, not VC-backed. Has nonprofit/school discounts, likely open to aligned partnerships. | |
| 174 | + | ||
| 175 | + | ### Fastmail | |
| 176 | + | ||
| 177 | + | Independent email, anti-Google, sustainable business. Similar "boring sustainable infrastructure" positioning. | |
| 178 | + | ||
| 179 | + | ### DuckDuckGo | |
| 180 | + | ||
| 181 | + | No search tracking. EFF organizational member. Note: has taken some outside investment, so verify current alignment. | |
| 182 | + | ||
| 183 | + | ### Purism | |
| 184 | + | ||
| 185 | + | Social Purpose Corporation (legally binding ethical commitments). Open source hardware and software. Privacy-first. Has turned down acquisition offers. | |
| 186 | + | ||
| 187 | + | ### Nitrokey | |
| 188 | + | ||
| 189 | + | Open source hardware security keys. Self-financed, mission-driven, full transparency. | |
| 190 | + | ||
| 191 | + | --- | |
| 192 | + | ||
| 193 | + | ## Hardware / Maker | |
| 194 | + | ||
| 195 | + | ### System76 | |
| 196 | + | ||
| 197 | + | Open source hardware/software (Pop!_OS). "Your computer is yours." Right-to-repair ethos. | |
| 198 | + | ||
| 199 | + | ### Fairphone | |
| 200 | + | ||
| 201 | + | Modular, repairable, 8+ year software support. Ethical manufacturing. iFixit certified. Already collaborates with privacy-focused OS providers. | |
| 202 | + | ||
| 203 | + | ### PINE64 | |
| 204 | + | ||
| 205 | + | Community-run open hardware. "FOSS principles guide our business." Non-profit adjacent governance. | |
| 206 | + | ||
| 207 | + | ### Teenage Engineering | |
| 208 | + | ||
| 209 | + | Design-forward, anti-commodity. Makes tools for independent musicians and creators. Their audience is our audience. | |
| 210 | + | ||
| 211 | + | ### RODE | |
| 212 | + | ||
| 213 | + | Heavily invested in supporting independent creators. Runs competitions, sponsors podcasters and musicians. | |
| 214 | + | ||
| 215 | + | --- | |
| 216 | + | ||
| 217 | + | ## Ethical Consumer Brands | |
| 218 | + | ||
| 219 | + | Companies where the connection is values-based, not technical. Better suited for post-launch when we have audience. | |
| 220 | + | ||
| 221 | + | ### Patagonia | |
| 222 | + | ||
| 223 | + | Anti-corporate, environmental, values-driven. Sponsors aligned projects and causes. | |
| 224 | + | ||
| 225 | + | ### Dr. Bronner's | |
| 226 | + | ||
| 227 | + | B-corp, radical transparency, auditable supply chain. "Every claim is verifiable" maps to our source-available stance. | |
| 228 | + | ||
| 229 | + | ### DFTBA Records | |
| 230 | + | ||
| 231 | + | Hank Green's creator-owned merch and distribution company. Exists because creators got tired of middlemen. Non-tech analog to what we're building. | |
| 232 | + | ||
| 233 | + | ### Darn Tough / Leatherman | |
| 234 | + | ||
| 235 | + | "Buy once, own forever" brands. Lifetime warranty. Anti-planned-obsolescence. The physical-goods version of our anti-extraction argument. | |
| 236 | + | ||
| 237 | + | ### Ethical Consumer (UK) | |
| 238 | + | ||
| 239 | + | Not-for-profit cooperative. Rates 40,000+ brands on ethical criteria. Getting reviewed/featured by them is a trust signal. | |
| 240 | + | ||
| 241 | + | --- | |
| 242 | + | ||
| 243 | + | ## Creator Tool Companies | |
| 244 | + | ||
| 245 | + | ### Literature and Latte (Scrivener) | |
| 246 | + | ||
| 247 | + | By writers, for writers. No aggressive subscription model. "Tools adapt to you." Strong author/screenwriter community. | |
| 248 | + | ||
| 249 | + | --- | |
| 250 | + | ||
| 251 | + | ## Cooperative Networks | |
| 252 | + | ||
| 253 | + | ### Loomio | |
| 254 | + | ||
| 255 | + | Worker cooperative, open source. Democratic governance in product and company. One of the most structurally aligned cooperative tech businesses. | |
| 256 | + | ||
| 257 | + | ### CoTech (Cooperative Technologists) | |
| 258 | + | ||
| 259 | + | UK network of worker cooperatives building ethical tech. Gateway to the cooperative tech ecosystem. | |
| 260 | + | ||
| 261 | + | ### Open Collective | |
| 262 | + | ||
| 263 | + | Community-governed financial infrastructure for open source. Transitioned from startup to nonprofit. Anti-extraction model. | |
| 264 | + | ||
| 265 | + | --- | |
| 266 | + | ||
| 267 | + | ## Do Not Pursue | |
| 268 | + | ||
| 269 | + | - **Substack** -- VC-funded, content moderation controversies, misaligned incentives | |
| 270 | + | - **Gumroad** -- VC history, profitability-at-all-costs public statements | |
| 271 | + | - **Patreon** -- VC-backed, growing fees, enshittification case study | |
| 272 | + | - **Bandcamp** -- Values were excellent but corporate situation is uncertain post-Songtradr acquisition. Monitor. | |
| 273 | + | ||
| 274 | + | --- | |
| 275 | + | ||
| 276 | + | ## Priority Order | |
| 277 | + | ||
| 278 | + | Near-term (pre-launch, relationship-building): | |
| 279 | + | 1. FUTO (they fund exactly this) | |
| 280 | + | 2. EFF (formal program, real badge) | |
| 281 | + | 3. Sourcehut (already use, direct relationship) | |
| 282 | + | 4. Ghost Foundation (highest alignment + largest audience) | |
| 283 | + | 5. Buttondown, Micro.blog, Write.as (indie web cluster, easy warm intros between them) | |
| 284 | + | ||
| 285 | + | Medium-term (soft launch, first creators onboarded): | |
| 286 | + | 6. Framework, Proton, Nextcloud (formal applications) | |
| 287 | + | 7. iFixit, Small Technology Foundation (vocal amplifiers) | |
| 288 | + | 8. 37signals (cold outreach, high-signal endorsement if it lands) | |
| 289 | + | 9. Kagi, Obsidian (audience overlap) | |
| 290 | + | ||
| 291 | + | Post-launch (established audience): | |
| 292 | + | 10. Patagonia, Dr. Bronner's, DFTBA, ethical consumer brands | |
| 293 | + | 11. Hardware companies (System76, Fairphone, PINE64) | |
| 294 | + | 12. Cooperative networks |
| @@ -48,6 +48,7 @@ We read everything. We don't respond to pitches that clearly didn't read this pa | |||
| 48 | 48 | ||
| 49 | 49 | ## See Also | |
| 50 | 50 | ||
| 51 | + | - [Partnership Targets](./partnership-targets.md) — specific organizations we want to work with | |
| 51 | 52 | - [How We Work](../../public/about/how-we-work.md) — business model and pricing | |
| 52 | 53 | - [Service Level Agreement](../../public/about/guarantees.md) — binding commitments | |
| 53 | 54 | - [Payment Independence](./payment-independence.md) — our approach to payment vendors |
| @@ -112,6 +112,11 @@ sync.enableFor(table: "projects") | |||
| 112 | 112 | ||
| 113 | 113 | ## Pricing Strategy | |
| 114 | 114 | ||
| 115 | + | **Superseded.** The pricing model below was the original design. It has been replaced by the consolidated Simple/Builder model in [`synckit_pricing.md`](../../synckit_pricing.md). Kept here for historical context. | |
| 116 | + | ||
| 117 | + | <details> | |
| 118 | + | <summary>Original pricing (archived 2026-05-03)</summary> | |
| 119 | + | ||
| 115 | 120 | Two pricing modes. Developers choose the one that fits their stage and data profile. Both include E2E encryption, unlimited sync requests, all devices per user, conflict resolution, and automatic backups. | |
| 116 | 121 | ||
| 117 | 122 | ### Mode 1: Shared Pool (Simple) | |
| @@ -158,6 +163,8 @@ Minimum monthly bill: $5 (covers base infrastructure). | |||
| 158 | 163 | ||
| 159 | 164 | Developers can switch from Shared Pool to Per-User at any time. We expect most developers to start on Shared Pool and switch when they have enough usage data to benefit from per-user pricing. | |
| 160 | 165 | ||
| 166 | + | </details> | |
| 167 | + | ||
| 161 | 168 | ### Add-ons (Both Modes) | |
| 162 | 169 | ||
| 163 | 170 | - Realtime sync (WebSocket): +$10/month | |
| @@ -166,19 +173,20 @@ Developers can switch from Shared Pool to Per-User at any time. We expect most d | |||
| 166 | 173 | ||
| 167 | 174 | ### Compare to Competition | |
| 168 | 175 | ||
| 169 | - | - Firebase with 100k DAU performing millions of operations could cost $100+/month with high variability; Supabase would be $25/month predictably | |
| 170 | - | - SyncKit Shared Pool: $20/month with zero usage anxiety | |
| 171 | - | - SyncKit Per-User: scales linearly and predictably — a GO-type app with 10k users costs ~$50/month; an AF-type app with 1k heavy users costs ~$500/month, directly reflecting actual infrastructure load | |
| 176 | + | *See [`synckit_pricing.md`](../../synckit_pricing.md) for current pricing comparisons.* | |
| 172 | 177 | ||
| 173 | 178 | ### Revenue Model | |
| 174 | 179 | ||
| 175 | - | - Monthly subscriptions from developers (both modes) | |
| 180 | + | - Monthly subscriptions from developers (Simple and Builder modes) | |
| 176 | 181 | - Transaction fees on payments (Stripe ~3%) | |
| 177 | - | - Enterprise deals for white-label / self-hosted instances | |
| 178 | - | - Consulting for complex integrations | |
| 182 | + | - Enterprise deals for white-label / self-hosted instances (future) | |
| 179 | 183 | ||
| 180 | 184 | ### Unit Economics | |
| 181 | 185 | ||
| 186 | + | *See [`synckit_pricing.md`](../../synckit_pricing.md) for current base rates and margin analysis.* | |
| 187 | + | ||
| 188 | + | **Original estimates (archived, based on superseded tier model).** Note: "R2" should read "Hetzner Object Storage" (actual infrastructure). The $1.00 support cost is unrealistic — real developer support is $5-15/customer/month at low scale. | |
| 189 | + | ||
| 182 | 190 | **Shared Pool — Indie tier ($20/month)**: | |
| 183 | 191 | - Revenue: $20/month | |
| 184 | 192 | - Costs: ~$2.25/month (R2 $0.15, compute $0.50, Stripe $0.60, support $1.00) | |
| @@ -303,12 +311,7 @@ Package the system into a reusable SDK that other developers can use in their ap | |||
| 303 | 311 | ||
| 304 | 312 | ### Pricing Launch | |
| 305 | 313 | ||
| 306 | - | Launch with Shared Pool mode only (simpler to implement and explain). Add Per-User mode once usage data from early customers validates the tier boundaries. | |
| 307 | - | ||
| 308 | - | - **Free**: 100 active users, 1GB storage | |
| 309 | - | - **Indie**: $20/month — 50k users, 50GB | |
| 310 | - | - **Pro**: $100/month — 500k users, 500GB | |
| 311 | - | - Per-User mode: add after launch based on real usage patterns | |
| 314 | + | **Superseded.** See [`synckit_pricing.md`](../../synckit_pricing.md) for the current Simple/Builder pricing model. No free tier — application-based access with a 14-day unbilled trial period. | |
| 312 | 315 | ||
| 313 | 316 | ### Marketing | |
| 314 | 317 | ||
| @@ -460,7 +463,10 @@ Server: Merge, store, return conflicts if any | |||
| 460 | 463 | ||
| 461 | 464 | ## Business Model & Economics | |
| 462 | 465 | ||
| 463 | - | See **Pricing Strategy** section above for full tier details (Shared Pool + Per-User modes). | |
| 466 | + | **Superseded.** See [`synckit_pricing.md`](../../synckit_pricing.md) for the current Simple/Builder pricing model with base rates and margin analysis. The unit economics and growth projections below were based on the original Shared Pool/Per-User tier model and used Cloudflare R2 cost estimates (actual infrastructure is Hetzner Object Storage). The $1.00/customer/month support cost was unrealistic — real developer support for a sync SDK is $5-15/customer/month at low scale. | |
| 467 | + | ||
| 468 | + | <details> | |
| 469 | + | <summary>Original economics (archived 2026-05-03)</summary> | |
| 464 | 470 | ||
| 465 | 471 | ### Unit Economics | |
| 466 | 472 | ||
| @@ -506,6 +512,8 @@ Per-User margins are higher because pricing directly tracks infrastructure cost | |||
| 506 | 512 | - Self-hosted offering | |
| 507 | 513 | - Target: $100k+ MRR | |
| 508 | 514 | ||
| 515 | + | </details> | |
| 516 | + | ||
| 509 | 517 | --- | |
| 510 | 518 | ||
| 511 | 519 | ## Competitive Analysis | |
| @@ -687,7 +695,7 @@ Sequenced by dependency. See `docs/mnw/todo.md` (SyncKit phases) for current tas | |||
| 687 | 695 | ||
| 688 | 696 | ### Stage 5: Public Launch | |
| 689 | 697 | - [ ] Marketing site | |
| 690 | - | - [ ] Free tier | |
| 698 | + | - [ ] Application-based access flow (no free tier — see synckit_pricing.md) | |
| 691 | 699 | - [ ] Support system | |
| 692 | 700 | - [ ] Analytics & monitoring | |
| 693 | 701 |
| @@ -0,0 +1,110 @@ | |||
| 1 | + | # SyncKit VPS Separation | |
| 2 | + | ||
| 3 | + | Technical spec for running SyncKit on a dedicated VPS, separate from the main MNW server. | |
| 4 | + | ||
| 5 | + | ## Trigger | |
| 6 | + | ||
| 7 | + | Before the first external developer is accepted. Not needed at current scale (3 internal apps, no external customers). | |
| 8 | + | ||
| 9 | + | ## Why | |
| 10 | + | ||
| 11 | + | - **Resource isolation.** An external developer's app with real traffic should not compete with MNW's web server, Multithreaded, or PostgreSQL for CPU/memory. | |
| 12 | + | - **Failure domain separation.** A SyncKit crash or overload should not take down the creator platform. A MNW deploy should not interrupt sync traffic. | |
| 13 | + | - **Independent scaling.** SyncKit can be upgraded to a larger VPS without affecting MNW's infrastructure costs. | |
| 14 | + | - **Security boundary.** External developers' encrypted data is physically separated from MNW's user data, creator content, and payment records. | |
| 15 | + | ||
| 16 | + | ## Architecture | |
| 17 | + | ||
| 18 | + | ### Current (shared VPS) | |
| 19 | + | ||
| 20 | + | ``` | |
| 21 | + | Hetzner VPS (100.120.174.96) | |
| 22 | + | - Caddy (reverse proxy) | |
| 23 | + | - MNW server (Actix-Web) | |
| 24 | + | - Web routes | |
| 25 | + | - API routes | |
| 26 | + | - SyncKit routes (/api/sync/*) | |
| 27 | + | - Multithreaded proxy | |
| 28 | + | - PostgreSQL | |
| 29 | + | - ClamAV | |
| 30 | + | ``` | |
| 31 | + | ||
| 32 | + | ### Target (split) | |
| 33 | + | ||
| 34 | + | ``` | |
| 35 | + | Hetzner VPS 1 — MNW (100.120.174.96) | |
| 36 | + | - Caddy (reverse proxy, forwards /api/sync/* to VPS 2) | |
| 37 | + | - MNW server (web + API, no SyncKit routes) | |
| 38 | + | - PostgreSQL (MNW tables) | |
| 39 | + | - ClamAV | |
| 40 | + | ||
| 41 | + | Hetzner VPS 2 — SyncKit ($15-30/mo) | |
| 42 | + | - Caddy (TLS termination) | |
| 43 | + | - SyncKit server (Axum, extracted from MNW binary) | |
| 44 | + | - PostgreSQL (sync_log, sync_apps, sync_devices, sync_keys, sync_blobs, sync_key_rotations, ota_releases, ota_artifacts) | |
| 45 | + | - Tailscale for inter-VPS communication | |
| 46 | + | ``` | |
| 47 | + | ||
| 48 | + | ## Implementation Steps | |
| 49 | + | ||
| 50 | + | ### 1. Extract SyncKit into a standalone binary | |
| 51 | + | ||
| 52 | + | SyncKit routes, auth, and DB queries are already modular (`routes/synckit/`, `synckit_auth.rs`, `db/synckit.rs`, `db/models/synckit.rs`). The work is: | |
| 53 | + | ||
| 54 | + | - [ ] Create `synckit-server` binary target (or separate crate) that starts an Axum server with only SyncKit routes | |
| 55 | + | - [ ] Extract shared dependencies (config, DB pool, S3 client, rate limiting) into a shared library or duplicate the minimal set | |
| 56 | + | - [ ] SyncKit server needs: PostgreSQL connection, S3 credentials, JWT secret, rate limit config | |
| 57 | + | - [ ] SyncKit server does NOT need: session store, CSRF, template engine, ClamAV, email (Postmark), Stripe, MNW-specific middleware | |
| 58 | + | ||
| 59 | + | ### 2. Split the database | |
| 60 | + | ||
| 61 | + | SyncKit tables are already isolated by foreign key structure. No SyncKit table references MNW content tables (projects, items, blog_posts, etc.). The shared references are: | |
| 62 | + | ||
| 63 | + | - `sync_apps.creator_id` -> `users.id` (who created the app) | |
| 64 | + | - `sync_log.user_id` -> `users.id` (who pushed the change) | |
| 65 | + | - `sync_devices.user_id` -> `users.id` (who registered the device) | |
| 66 | + | ||
| 67 | + | Options: | |
| 68 | + | - **Option A: Shared PostgreSQL, separate schemas.** Simplest. Both VPSes connect to the same PostgreSQL on VPS 1. SyncKit uses a `synckit` schema. No data migration needed. | |
| 69 | + | - **Option B: Separate PostgreSQL instances.** Full isolation. SyncKit VPS runs its own PostgreSQL. User validation becomes an API call to MNW instead of a JOIN. Requires replicating or caching user status. | |
| 70 | + | - **Option C: Shared PostgreSQL initially, split later.** Start with Option A, migrate to B when scale demands it. | |
| 71 | + | ||
| 72 | + | Recommendation: **Option C.** Shared PostgreSQL is simpler and sufficient until SyncKit traffic justifies its own database. | |
| 73 | + | ||
| 74 | + | ### 3. Routing | |
| 75 | + | ||
| 76 | + | Caddy on VPS 1 proxies `/api/sync/*` and `/api/v1/sync/*` to VPS 2 over Tailscale. All other routes stay on VPS 1. | |
| 77 | + | ||
| 78 | + | ```caddy | |
| 79 | + | # On VPS 1 | |
| 80 | + | handle /api/sync/* { | |
| 81 | + | reverse_proxy 100.x.x.x:8080 # SyncKit VPS via Tailscale | |
| 82 | + | } | |
| 83 | + | handle /api/v1/sync/* { | |
| 84 | + | reverse_proxy 100.x.x.x:8080 | |
| 85 | + | } | |
| 86 | + | ``` | |
| 87 | + | ||
| 88 | + | ### 4. OTA updates | |
| 89 | + | ||
| 90 | + | OTA endpoints (`/api/sync/apps/{slug}/updates/*`) also move to VPS 2. S3 credentials for Hetzner Object Storage are shared (same bucket, different prefix if desired). | |
| 91 | + | ||
| 92 | + | ### 5. Monitoring | |
| 93 | + | ||
| 94 | + | - PoM monitors both VPSes independently | |
| 95 | + | - SyncKit VPS gets its own health check endpoint | |
| 96 | + | - Alert on: VPS unreachable, PostgreSQL connection failures, high error rate, disk usage | |
| 97 | + | ||
| 98 | + | ## Cost | |
| 99 | + | ||
| 100 | + | - Hetzner CX22 (2 vCPU, 4 GB RAM): ~$5/mo | |
| 101 | + | - Hetzner CX32 (4 vCPU, 8 GB RAM): ~$15/mo | |
| 102 | + | - Hetzner CX42 (8 vCPU, 16 GB RAM): ~$30/mo | |
| 103 | + | ||
| 104 | + | Start with CX22 ($5/mo). Upgrade when monitoring shows resource pressure. | |
| 105 | + | ||
| 106 | + | ## Timeline | |
| 107 | + | ||
| 108 | + | Not urgent. Execute when: | |
| 109 | + | 1. First external developer application is approved, OR | |
| 110 | + | 2. SyncKit traffic from internal apps exceeds 10% of VPS resource usage |
| @@ -4,71 +4,70 @@ A detailed breakdown of what it costs to run Makenot.work. These numbers reflect | |||
| 4 | 4 | ||
| 5 | 5 | ## Fixed Costs | |
| 6 | 6 | ||
| 7 | - | These exist regardless of how many creators use the platform. | |
| 7 | + | These exist regardless of how many creators use the platform. **Actual** = what we pay today. **Budgeted** = what we expect to pay soon or should budget for. | |
| 8 | 8 | ||
| 9 | - | ### Infrastructure | |
| 9 | + | ### Infrastructure (Hetzner) | |
| 10 | 10 | ||
| 11 | - | | Component | Monthly Cost | Notes | | |
| 12 | - | |-----------|--------------|-------| | |
| 13 | - | | Application servers | $50–200 | Scales with traffic; floor is one small instance | | |
| 14 | - | | Database | $30–150 | PostgreSQL; managed service or self-hosted | | |
| 15 | - | | Redis (cache/queues) | $15–50 | Small instance sufficient at current scale | | |
| 16 | - | | Object storage | $20–100 | Base cost before per-creator storage | | |
| 17 | - | | Load balancer | $20–50 | Required for HTTPS termination | | |
| 18 | - | | **Subtotal** | **$135–550** | | | |
| 11 | + | Source: Invoice 081000817566 (March 2026, $31.00 total). | |
| 19 | 12 | ||
| 20 | - | We use commodity cloud infrastructure. No vendor lock-in—everything runs on standard services available from multiple providers. | |
| 13 | + | | Component | Actual | Notes | | |
| 14 | + | |-----------|--------|-------| | |
| 15 | + | | CCX13 cloud server (production) | $14.00 | MNW server + PostgreSQL + Redis, 601 hrs/mo | | |
| 16 | + | | CCX13 backup (20% of instance) | $2.80 | Automated backups | | |
| 17 | + | | CPX11 cloud server x2 (CI/astra) | $5.96 | Self-hosted CI runner + build server | | |
| 18 | + | | Primary IPv4 x3 | $1.35 | One per server ($0.60 flat + $0.75 hourly) | | |
| 19 | + | | Volume storage (18 GB) | $0.90 | Persistent block storage | | |
| 20 | + | | Object storage (S3-compatible) | $5.99 | Base cost; no overage yet | | |
| 21 | + | | Bucket storage + traffic | $0.00 | Negligible at current scale | | |
| 22 | + | | Additional traffic | $0.00 | 1 TB included per server, not exceeded | | |
| 23 | + | | **Subtotal** | **$31.00** | | | |
| 24 | + | ||
| 25 | + | All infrastructure runs on Hetzner Cloud. App server, database, Redis, and object storage on one provider. No separate managed database, no separate cache service, no load balancer (Caddy handles HTTPS termination on the VPS directly). | |
| 21 | 26 | ||
| 22 | 27 | ### Operations | |
| 23 | 28 | ||
| 24 | - | | Component | Monthly Cost | Notes | | |
| 25 | - | |-----------|--------------|-------| | |
| 26 | - | | Domain registration | $2–5 | Amortized annually | | |
| 27 | - | | SSL certificates | $0–10 | Let's Encrypt is free; some wildcards cost | | |
| 28 | - | | DNS hosting | $5–20 | Depends on query volume | | |
| 29 | - | | Monitoring & alerting | $20–80 | Uptime, performance, error tracking | | |
| 30 | - | | Security scanning | $0–50 | Mix of free and paid tools | | |
| 31 | - | | Log aggregation | $20–50 | Retention and searchability | | |
| 32 | - | | **Subtotal** | **$47–215** | | | |
| 29 | + | | Component | Actual | Budgeted | Notes | | |
| 30 | + | |-----------|--------|----------|-------| | |
| 31 | + | | Cloudflare (DNS + CDN) | $0 | $25 | Free plan now; budget for Pro ($25/domain/mo) | | |
| 32 | + | | Domain registration | ~$5 | $5 | Amortized annually across domains | | |
| 33 | + | | SSL certificates | $0 | $0 | Let's Encrypt via Caddy, automatic | | |
| 34 | + | | Postmark (transactional email) | ~$0 | $15–50 | Minimal usage now; budget for growth | | |
| 35 | + | | Monitoring & alerting | $0 | $0 | PoM (self-hosted), Tailscale/Headscale | | |
| 36 | + | | **Subtotal** | **~$5** | **$45–80** | | | |
| 33 | 37 | ||
| 34 | 38 | ### Business | |
| 35 | 39 | ||
| 36 | - | | Component | Monthly Cost | Notes | | |
| 37 | - | |-----------|--------------|-------| | |
| 38 | - | | Payment processor (platform billing) | $50–100 | Stripe fees on creator subscriptions | | |
| 39 | - | | Accounting software | $0–30 | Basic bookkeeping | | |
| 40 | - | | Legal reserve | $100–300 | Ongoing counsel after one-time foundations ($5,750–14,350, see `pitch.md`); amortized, actual costs are lumpy | | |
| 41 | - | | Business insurance | $50–100 | Liability coverage | | |
| 42 | - | | State/local compliance | $20–50 | Business licenses, registered agent | | |
| 43 | - | | **Subtotal** | **$220–580** | | | |
| 40 | + | | Component | Actual | Budgeted | Notes | | |
| 41 | + | |-----------|--------|----------|-------| | |
| 42 | + | | Coworking — Irvine | $332 | $332 | Industrious, active 2026-05-01, month-to-month | | |
| 43 | + | | Coworking — Boulder | — | ~$332 | Expected, not yet signed | | |
| 44 | + | | Stripe platform fees | $0 | $0 | Standard Connect; no per-account or platform fees | | |
| 45 | + | | Legal reserve | $0 | $100–300 | Amortized; actual spend is lumpy (see `pitch.md`) | | |
| 46 | + | | Business insurance | $0 | $50–100 | Not yet active | | |
| 47 | + | | State/local compliance | ~$5 | $20 | CO registered agent, business license amortized | | |
| 48 | + | | Accounting software | $0 | $0–30 | Manual for now | | |
| 49 | + | | **Subtotal** | **~$337** | **$834–1,114** | | | |
| 44 | 50 | ||
| 45 | 51 | ### Development | |
| 46 | 52 | ||
| 47 | - | | Component | Monthly Cost | Notes | | |
| 48 | - | |-----------|--------------|-------| | |
| 49 | - | | GitHub/GitLab | $0–20 | Free tier works; paid for private CI | | |
| 50 | - | | CI/CD | $0–50 | Build minutes | | |
| 51 | - | | Development environments | $0–30 | Local or cloud dev boxes | | |
| 52 | - | | **Subtotal** | **$0–100** | | | |
| 53 | + | | Component | Actual | Budgeted | Notes | | |
| 54 | + | |-----------|--------|----------|-------| | |
| 55 | + | | Claude Code (Max plan) | $200 | $200 | Primary development tool | | |
| 56 | + | | Git hosting (Sourcehut) | $0 | $0 | Personal expense, not business | | |
| 57 | + | | CI/CD | $0 | $0 | Self-hosted on astra (included in Hetzner) | | |
| 58 | + | | **Subtotal** | **$200** | **$200** | | | |
| 53 | 59 | ||
| 54 | 60 | ### Fixed Cost Summary | |
| 55 | 61 | ||
| 56 | - | | Category | Low | High | | |
| 57 | - | |----------|-----|------| | |
| 58 | - | | Infrastructure | $135 | $550 | | |
| 59 | - | | Operations | $47 | $215 | | |
| 60 | - | | Business | $220 | $580 | | |
| 61 | - | | Development | $0 | $100 | | |
| 62 | - | | **Total Fixed** | **$402** | **$1,445** | | |
| 63 | - | ||
| 64 | - | **Current actual: ~$600/month** at minimal scale. | |
| 62 | + | | Category | Actual | Budgeted | | |
| 63 | + | |----------|--------|----------| | |
| 64 | + | | Infrastructure | $31 | $31 | | |
| 65 | + | | Operations | ~$5 | $45–80 | | |
| 66 | + | | Business | ~$337 | $834–1,114 | | |
| 67 | + | | Development | $200 | $200 | | |
| 68 | + | | **Total Fixed** | **~$573** | **$1,110–1,425** | | |
| 65 | 69 | ||
| 66 | - | The range exists because: | |
| 67 | - | - Infrastructure scales somewhat even within "fixed" category | |
| 68 | - | - Some costs are optional (paid monitoring vs. free) | |
| 69 | - | - Legal/insurance costs vary by state and coverage level | |
| 70 | - | ||
| 71 | - | **Not yet active** (included in high-end estimates): business insurance ($50–100/mo), paid monitoring ($20–80/mo), paid security scanning ($0–50/mo), accounting software ($0–30/mo). These account for most of the gap between the $402 low and ~$600 actual. | |
| 70 | + | **Current actual: ~$573/month.** Budgeted range includes Cloudflare Pro, Postmark growth, Boulder coworking, legal reserve, and business insurance — all expected but not yet active. | |
| 72 | 71 | ||
| 73 | 72 | ## Variable Costs (Per-Creator) | |
| 74 | 73 | ||
| @@ -169,21 +168,23 @@ Things that cost other platforms money but don't cost us: | |||
| 169 | 168 | | Data analytics infrastructure | Privacy-first; minimal data collection | | |
| 170 | 169 | | Content moderation at scale | Smaller creator base; manageable manually | | |
| 171 | 170 | | Investor relations | Self-funded | | |
| 172 | - | | Office space | Remote/solo operation | | |
| 171 | + | | Office lease | Coworking via Industrious ($332/mo Irvine); no long-term lease | | |
| 173 | 172 | ||
| 174 | 173 | This isn't virtue signaling—it's structural. These costs would require revenue to cover them, which would require either higher prices or taking a cut of creator earnings. | |
| 175 | 174 | ||
| 176 | 175 | ## Cost Projections | |
| 177 | 176 | ||
| 177 | + | Projections use **budgeted** costs (assumes Cloudflare Pro, Postmark, Boulder coworking all active — worst-case fixed baseline of ~$1,200/mo). | |
| 178 | + | ||
| 178 | 179 | ### At 100 Creators (Mixed Tiers) | |
| 179 | 180 | ||
| 180 | 181 | | Category | Monthly | | |
| 181 | 182 | |----------|---------| | |
| 182 | - | | Fixed costs | ~$600 | | |
| 183 | + | | Fixed costs | ~$1,200 | | |
| 183 | 184 | | Variable costs (~$3 avg) | ~$300 | | |
| 184 | - | | **Total** | **~$900** | | |
| 185 | + | | **Total** | **~$1,500** | | |
| 185 | 186 | | Revenue (~$24 avg) | ~$2,400 | | |
| 186 | - | | **Surplus** | **~$1,500** | | |
| 187 | + | | **Surplus** | **~$900** | | |
| 187 | 188 | ||
| 188 | 189 | Sustainable with healthy margin. | |
| 189 | 190 | ||
| @@ -191,11 +192,11 @@ Sustainable with healthy margin. | |||
| 191 | 192 | ||
| 192 | 193 | | Category | Monthly | | |
| 193 | 194 | |----------|---------| | |
| 194 | - | | Fixed costs | ~$800 (some scaling) | | |
| 195 | + | | Fixed costs | ~$1,300 (infra scaling) | | |
| 195 | 196 | | Variable costs | ~$1,500 | | |
| 196 | - | | **Total** | **~$2,300** | | |
| 197 | + | | **Total** | **~$2,800** | | |
| 197 | 198 | | Revenue | ~$12,000 | | |
| 198 | - | | **Surplus** | **~$9,700** | | |
| 199 | + | | **Surplus** | **~$9,200** | | |
| 199 | 200 | ||
| 200 | 201 | Comfortable one-person operation with strong reserves. | |
| 201 | 202 | ||
| @@ -203,11 +204,11 @@ Comfortable one-person operation with strong reserves. | |||
| 203 | 204 | ||
| 204 | 205 | | Category | Monthly | | |
| 205 | 206 | |----------|---------| | |
| 206 | - | | Fixed costs | ~$1,500 (more scaling) | | |
| 207 | + | | Fixed costs | ~$1,600 (more scaling) | | |
| 207 | 208 | | Variable costs | ~$6,000 | | |
| 208 | - | | **Total** | **~$7,500** | | |
| 209 | + | | **Total** | **~$7,600** | | |
| 209 | 210 | | Revenue | ~$48,000 | | |
| 210 | - | | **Surplus** | **~$40,500** | | |
| 211 | + | | **Surplus** | **~$40,400** | | |
| 211 | 212 | ||
| 212 | 213 | Could support a small team with excellent margins. | |
| 213 | 214 |
| @@ -1,110 +1,139 @@ | |||
| 1 | 1 | # SyncKit Pricing | |
| 2 | 2 | ||
| 3 | - | SyncKit is E2E encrypted cloud sync and OTA updates for indie apps. Pricing is built on two variables the developer controls: **weight** (storage) and **burst** (transfer multiplier). This design lets developers pay for their actual access pattern instead of fitting into predetermined tiers. | |
| 3 | + | E2E encrypted cloud sync and OTA updates for indie apps. Two modes, one billing engine, no surprises. | |
| 4 | 4 | ||
| 5 | - | ## Core Concepts | |
| 5 | + | ## Principles | |
| 6 | 6 | ||
| 7 | - | **Weight** is how much data you store, priced per GB per month. | |
| 7 | + | 1. **Easy to understand.** Simple mode requires one decision (how much storage). Builder mode adds one more knob (transfer ratio). That's it. | |
| 8 | + | 2. **Friendly to power users.** Developers who understand their usage pattern can optimize with Builder mode. Developers who don't can stay on Simple forever. | |
| 9 | + | 3. **Priced relative to actual costs.** Base rates are derived from real infrastructure costs with published margins. No opaque markup. | |
| 10 | + | 4. **Always predictable.** The bill is known before the billing period starts. There are no overages. When limits are hit, sync degrades gracefully — it never charges more. Developers always have a chance to say no before paying more. | |
| 11 | + | 5. **Easy to enter and leave.** Apply to get started, export your data at any time, cancel takes effect at end of billing period. Standard formats, no lock-in, no retention games. | |
| 8 | 12 | ||
| 9 | - | **Burst** is how much transfer you get relative to your storage. A burst of 5x means your monthly transfer budget is 5 times your storage allocation. The developer chooses their burst multiplier based on how their app behaves — a notes app that syncs small deltas needs low burst; a sample manager where users set up new devices needs high burst. | |
| 13 | + | ## Getting Started | |
| 10 | 14 | ||
| 11 | - | **Billing guarantee:** In the pool model and in the per-user model with overage disabled, the bill never exceeds the configured amount. No surprises. | |
| 15 | + | No free tier. Apply for access with a short description of your app and expected usage. Same reasoning as MNW creator subscriptions: a free tier attracts users who don't value the service, creates support burden without revenue, and dilutes the quality of the developer community. The application filters for developers who are serious about shipping. | |
| 16 | + | ||
| 17 | + | Accepted developers get full access immediately. First 14 days are not billed — the trial period starts when the application is approved, not when the first sync happens. | |
| 12 | 18 | ||
| 13 | 19 | ## Base Rates | |
| 14 | 20 | ||
| 15 | - | | Variable | Unit | Price | | |
| 16 | - | |----------|------|-------| | |
| 17 | - | | Weight | per GB stored per month | $0.15 | | |
| 18 | - | | Burst | per multiplier unit per GB of weight | $0.03 | | |
| 21 | + | | Variable | Unit | Price | Infra cost | Margin | | |
| 22 | + | |----------|------|-------|------------|--------| | |
| 23 | + | | Weight | per GB stored per month | $0.15 | ~$0.007/GB (Hetzner Object Storage) | ~95% | | |
| 24 | + | | Burst | per multiplier unit per GB of weight | $0.03 | ~$0.01/GB egress | ~67% | | |
| 19 | 25 | ||
| 20 | 26 | Monthly cost = (weight in GB x $0.15) + (burst multiplier x weight in GB x $0.03) | |
| 21 | 27 | ||
| 22 | - | ## Model A: Developer Pool | |
| 28 | + | These margins accommodate moving to more expensive infrastructure (e.g., AWS S3 at $0.023/GB storage, $0.09/GB egress) without changing customer pricing. Weight margin drops to ~85% on AWS; burst margin drops to ~0%. Hetzner is the target infrastructure. | |
| 29 | + | ||
| 30 | + | API requests are included. No per-request charges. Abuse is handled as a ToS issue, not a billing event. | |
| 31 | + | ||
| 32 | + | ## Simple Mode | |
| 23 | 33 | ||
| 24 | - | The developer buys a fixed storage allocation and burst multiplier for all their users combined. Best for apps with small per-user data or shared content. | |
| 34 | + | The developer chooses **weight** (storage in GB). Burst is set to a platform-default ratio — currently **5x**. The monthly cost is the Builder formula applied to these inputs. | |
| 35 | + | ||
| 36 | + | Simple mode is Builder mode with a fixed burst ratio. There is no markup, no hidden difference in the billing engine. A Simple customer paying for 20 GB of weight at 5x burst pays exactly what a Builder customer would pay for the same configuration. | |
| 25 | 37 | ||
| 26 | 38 | ### Example configurations | |
| 27 | 39 | ||
| 28 | - | | App type | Weight | Burst | Monthly cost | | |
| 29 | - | |----------|--------|-------|-------------| | |
| 30 | - | | Config/state sync (feed reader) | 5 GB | 10x | $2.25 | | |
| 31 | - | | Productivity app (tasks, contacts) | 20 GB | 10x | $9.00 | | |
| 32 | - | | File sync (sample libraries) | 200 GB | 5x | $60.00 | | |
| 40 | + | | App type | Weight | Burst (fixed 5x) | Monthly cost | | |
| 41 | + | |----------|--------|-------------------|-------------| | |
| 42 | + | | Config/state sync (settings, read state) | 1 GB | 5x | $0.30 | | |
| 43 | + | | Productivity (tasks, contacts, light files) | 10 GB | 5x | $4.50 | | |
| 44 | + | | Media metadata (sample libraries, playlists) | 50 GB | 5x | $22.50 | | |
| 45 | + | | Large file sync (audio, video, courses) | 200 GB | 5x | $60.00 | | |
| 46 | + | ||
| 47 | + | ### Ratio drift | |
| 48 | + | ||
| 49 | + | The default burst ratio may change over time based on aggregate usage data from Simple mode customers. If most apps need 7x burst instead of 5x, the default will be updated. | |
| 33 | 50 | ||
| 34 | - | ### Limits | |
| 51 | + | When the ratio changes: | |
| 52 | + | - Existing Simple customers stay on their current ratio unless they opt in to the new one | |
| 53 | + | - New Simple customers get the new ratio | |
| 54 | + | - The change is announced with at least 30 days notice | |
| 55 | + | - Any customer can switch to Builder mode at any time to set their own ratio | |
| 35 | 56 | ||
| 36 | - | - Storage full: new uploads rejected, existing sync continues | |
| 37 | - | - Transfer budget hit: sync deprioritized (queued with backoff between batches) | |
| 38 | - | - No overages. Upgrade weight or burst to increase capacity. | |
| 57 | + | ## Builder Mode | |
| 39 | 58 | ||
| 40 | - | ## Model B: Per-User Seats | |
| 59 | + | The developer chooses both **weight** (storage in GB) and **burst** (transfer multiplier) independently. Best for launched apps where the developer understands their usage pattern and wants to optimize cost. | |
| 41 | 60 | ||
| 42 | - | The developer sets per-user weight and burst allocations. Each user who syncs at least once in a billing period is an active seat. Best for apps where data scales linearly with users. | |
| 61 | + | ### How burst works | |
| 62 | + | ||
| 63 | + | Burst is the transfer budget relative to storage. A burst of 5x on 20 GB of weight means 100 GB of monthly transfer included. The developer picks the multiplier based on how their app behaves. | |
| 64 | + | ||
| 65 | + | | App pattern | Suggested burst | Why | | |
| 66 | + | |-------------|----------------|-----| | |
| 67 | + | | Small metadata, few devices, incremental sync | 3-5x | Low transfer relative to storage | | |
| 68 | + | | Light attachments, occasional new device setup | 8-10x | New device pulls full dataset | | |
| 69 | + | | Large libraries, infrequent full syncs | 2-3x | High storage, low transfer ratio | | |
| 70 | + | | Collaborative editing, constant syncing | 10-15x | Low storage, high transfer frequency | | |
| 43 | 71 | ||
| 44 | 72 | ### Example configurations | |
| 45 | 73 | ||
| 46 | - | | App type | Weight/user | Burst | Base cost/user | At 1,000 users | | |
| 47 | - | |----------|-------------|-------|---------------|----------------| | |
| 48 | - | | Feed reader (read state, bookmarks) | 5 MB | 5x | $0.0015 | $1.50/mo | | |
| 49 | - | | Productivity (tasks, contacts, light attachments) | 100 MB | 10x | $0.045 | $45/mo | | |
| 50 | - | | Sample manager (metadata + selective blob sync) | 5 GB | 3x | $1.20 | $1,200/mo | | |
| 74 | + | | App type | Weight | Burst | Monthly cost | | |
| 75 | + | |----------|--------|-------|-------------| | |
| 76 | + | | Feed reader (read state, bookmarks) | 5 GB | 10x | $2.25 | | |
| 77 | + | | Productivity app (tasks, contacts) | 20 GB | 10x | $9.00 | | |
| 78 | + | | Sample manager (metadata + selective blob) | 200 GB | 3x | $48.00 | | |
| 79 | + | | Collaborative editor (small docs, constant sync) | 5 GB | 15x | $3.00 | | |
| 80 | + | ||
| 81 | + | ### Adjusting configuration | |
| 82 | + | ||
| 83 | + | Developers can change their weight and burst settings monthly. The new configuration takes effect at the start of the next billing period. The dashboard shows the projected cost before the developer commits. | |
| 84 | + | ||
| 85 | + | ## What Happens at Limits | |
| 51 | 86 | ||
| 52 | - | ### Burst overage (per-user model only) | |
| 87 | + | **Storage full:** New uploads are rejected. Existing sync continues. The developer sees a dashboard alert and can increase weight. | |
| 53 | 88 | ||
| 54 | - | Developers can optionally enable burst overage on a per-app basis. This is the one place overages exist, and they are capped. | |
| 89 | + | **Transfer budget exhausted:** Sync is deprioritized — changes are queued with backoff between batches. No data loss, just slower sync until the next billing period. The developer can increase burst to restore full-speed sync. | |
| 55 | 90 | ||
| 56 | - | | Condition | Behavior | | |
| 57 | - | |-----------|----------| | |
| 58 | - | | Within burst budget | Normal sync | | |
| 59 | - | | Over budget, overage **disabled** (default) | Sync deprioritized — queued with backoff | | |
| 60 | - | | Over budget, overage **enabled** | $0.05/GB over budget, capped at 2x the burst budget | | |
| 61 | - | | 2x cap reached | Throttled regardless, no further charges | | |
| 91 | + | **In both cases:** The bill does not change. There are no overages. The developer chose a configuration, and that configuration's price is the price. Degraded service is the signal to upgrade, not a surprise invoice. | |
| 62 | 92 | ||
| 63 | - | Default is **off**. Developers who prefer paying a small premium over degrading user experience can opt in, with a known ceiling. | |
| 93 | + | ## Per-User vs Pool | |
| 64 | 94 | ||
| 65 | - | A developer buying 5 GB weight, 3x burst, overage enabled: | |
| 66 | - | - Burst budget: 15 GB/mo transfer (included) | |
| 67 | - | - Overage cap: 30 GB additional (2x burst budget) | |
| 68 | - | - Overage cost at cap: $1.50 (30 GB x $0.05) | |
| 69 | - | - Maximum possible bill per user: $1.20 base + $0.75 max overage = $1.95 | |
| 95 | + | SyncKit bills the **developer**, not individual end users. The developer buys a storage and transfer budget for their entire app. How they allocate that across their users is their business — SyncKit doesn't track or bill per-user. | |
| 70 | 96 | ||
| 71 | - | The worst case is always calculable before the developer ships. | |
| 97 | + | A developer with 10,000 users and 10 GB of weight is paying for 10 GB total, not 10 GB per user. If their users collectively need more, the developer increases weight. | |
| 72 | 98 | ||
| 73 | - | ## How burst maps to real usage | |
| 99 | + | This keeps billing dead simple and predictable. The developer knows their bill before the month starts. They can charge their users whatever they want — flat fee, freemium, usage-based, or nothing. SyncKit doesn't care. | |
| 74 | 100 | ||
| 75 | - | The main driver of burst is new device setup — a user adding a device pulls their entire dataset. The developer can estimate this: | |
| 101 | + | ## What's Included (Both Modes) | |
| 76 | 102 | ||
| 77 | - | | Scenario | Weight | Burst needed | | |
| 78 | - | |----------|--------|-------------| | |
| 79 | - | | Metadata sync, 2-3 devices, incremental | 100 MB | 3-5x | | |
| 80 | - | | Light attachments, occasional new device | 500 MB | 8-10x | | |
| 81 | - | | Full blob sync, users add devices monthly | 5 GB | 5-8x | | |
| 82 | - | | Large libraries, infrequent new devices | 20 GB | 2-3x | | |
| 103 | + | - E2E encryption (ChaCha20-Poly1305 + Argon2 key derivation) | |
| 104 | + | - Unlimited sync requests (no per-request billing) | |
| 105 | + | - All devices per user (no per-device fees) | |
| 106 | + | - Conflict resolution (last-write-wins, field-level merge) | |
| 107 | + | - Blob storage (within weight allocation) | |
| 108 | + | - OTA update distribution | |
| 109 | + | - Device management | |
| 110 | + | - Dashboard with usage stats, per-user breakdown, budget alerts at 80% | |
| 111 | + | - Data export at any time (standard format) | |
| 83 | 112 | ||
| 84 | - | Apps with large data but infrequent full syncs (sample managers) buy high weight, low burst. Apps with small data but constant syncing (collaborative editors) buy low weight, high burst. Each pays for what they use. | |
| 113 | + | ## Data Portability | |
| 85 | 114 | ||
| 86 | - | ## API requests | |
| 115 | + | SyncKit stores encrypted data the server cannot read. The developer holds the keys. | |
| 87 | 116 | ||
| 88 | - | Included. No per-request charges. If abuse occurs it is handled as a ToS issue, not a billing event. | |
| 117 | + | Export is available at any time via API or dashboard: | |
| 118 | + | - Full sync log export (encrypted, developer decrypts client-side) | |
| 119 | + | - Device and key metadata | |
| 120 | + | - Usage history and billing records | |
| 89 | 121 | ||
| 90 | - | ## Dashboard | |
| 122 | + | Cancellation takes effect at end of billing period. Data is retained for 30 days after cancellation, then permanently deleted. The developer can export during this window. | |
| 91 | 123 | ||
| 92 | - | The developer dashboard shows: | |
| 93 | - | - Current weight used (per user and aggregate) | |
| 94 | - | - Transfer consumed vs budget (current billing period) | |
| 95 | - | - Per-user breakdown (top consumers, users near limits) | |
| 96 | - | - Overage status (if enabled) with projected cost | |
| 124 | + | ## Future Add-Ons | |
| 97 | 125 | ||
| 98 | - | Alerts at 80% of storage or transfer budget via email and dashboard notification. | |
| 126 | + | These are planned capabilities with real marginal costs, priced separately when they ship: | |
| 99 | 127 | ||
| 100 | - | ## Margins | |
| 128 | + | - **Realtime sync** (WebSocket/SSE push) — pricing TBD based on connection costs | |
| 129 | + | - **Custom domain** — pricing TBD | |
| 130 | + | - **Priority support** — pricing TBD | |
| 101 | 131 | ||
| 102 | - | At Hetzner Object Storage rates (~$0.007/GB storage, ~$0.01/GB egress after 1 TB free), the margin structure is: | |
| 132 | + | Add-ons will follow the same principles: predictable, cost-relative, no surprises. | |
| 103 | 133 | ||
| 104 | - | | Rate | Raw cost | Our price | Margin | | |
| 105 | - | |------|----------|-----------|--------| | |
| 106 | - | | Weight ($0.15/GB) | $0.007/GB | $0.15/GB | ~95% | | |
| 107 | - | | Burst ($0.03/unit/GB) | $0.01/GB egress | $0.03/GB | ~67% | | |
| 108 | - | | Overage ($0.05/GB) | $0.01/GB | $0.05/GB | ~80% | | |
| 134 | + | ## See Also | |
| 109 | 135 | ||
| 110 | - | These margins accommodate moving to AWS S3 ($0.023/GB storage, $0.09/GB egress) if needed, though at reduced margin (~85% weight, ~0% burst on AWS). Hetzner is the target infrastructure. | |
| 136 | + | - [SyncKit architecture](../shared/synckit-client/docs/architecture.md) | |
| 137 | + | - [SyncKit competition analysis](../shared/synckit-client/docs/competition.md) | |
| 138 | + | - [MNW economics](internal/business/economics.md) — SyncKit as MNW add-on | |
| 139 | + | - [Fan+ design](internal/business/fan-plus.md) — consumer subscription context |