Skip to main content

max / makenotwork

v0.6.5: UX audit consolidation + inline-style sweep + founder pricing Two-track release. Pre-Phase-1 UX audit consolidation lands alongside soft-launch founder-pricing engineering that had been WIP. UX audit consolidation pass (Phases A-K) - Inline style="..." attributes: 1,276 → 6 across 100+ templates. The six remaining are server-computed {{pct}}% width/height exceptions (chart bars, storage fill, revenue bar, checklist progress). - Per-tab CSS sections promoted to canonical primitives: * .progress-bar-container + .progress-bar with --slim, --rounded, --highlight modifiers (replaces .wiz-progress-*, .batch-progress-*, .checklist-progress-*, scoped .import-page .progress-bar) * .upload-status with __row + __msg.is-success/.is-error * .empty-state (replaces 7 per-tab *-empty classes) * .field-status / .save-status aliased with .success/.error/.saving * .section-lead (replaces 9 per-tab leads) * .callout with --danger / --warning / --solid-warning (replaces .account-callout*, .cart-warning, .dns-callout*) * .list-row primitive aliased to .psection-row, .section-mgmt-row, .bundle-picker-row, .checklist-row * .small recipe aliased to .btn-tiny, .cart-row-btn, .library-row-btn * .card--bordered absorbs .tier-card, .feature-card, .use-case-card, .fork-card; .card-muted absorbs .account-tip-card, .account-status-card * .minw-300..800 utilities replace per-tab min-width table classes - style.css 11,267 → 10,900 (−367 lines). Removed 179 lines of identical duplicate section blocks left by parallel-agent appends, plus dead scope rules where the body class never existed. - JS handlers refactored to toggle .hidden / .is-error / .is-faded classes instead of mutating style.display, style.color, style.opacity (insertions.js, project-sections.js, blog-editor.js, item-details.js). - Broken inline color refs (--success-color, --error-color, --warning-color, --accent-color, --primary-color — none of which exist as vars) fixed by mapping to real tokens (--success, --error, --warning, --accent, --primary-dark). - Several dead <style> blocks removed (creators.html, receipt.html, dashboard-import.html, stripe_disclaimer.html, item_embed.html, dashboard-blog-editor.html). Founder pricing engineering - New migration 116_founder_pricing.sql adds annual/founder Price ID columns and founder_window tracking. - Config gains creator_tier_annual_prices, creator_tier_founder_prices, creator_tier_founder_annual_prices maps and creator_founder_window_open flag. - Stripe checkout/subscriptions, payments/webhooks, auth, admin routes, user models updated to honor founder pricing + window state. - Pricing site-docs (pricing.md, guide/stripe.md, guide/tiers.md) updated with founder pricing copy. Stripe rc.5 migration docs leftovers consolidated. Per remediation-plan.md success criteria: inline-style grep under 100 (6), no checkmark glyphs in any template, no Bootstrap/#000/#fff literals in CSS, every "selected" state is .is-selected, charter primitive table has canonical class per row.
Co-Authored-By
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-20 21:31 UTC
Commit: 59108584214e4c90541a64894e912972c6bab771
Parent: 21b99d5
200 files changed, +5864 insertions, -4621 deletions
M .gitignore +3
@@ -40,3 +40,6 @@
40 40 # Mutation testing output
41 41 mutants.out*
42 42 **/mutants.out*
43 +
44 + # Claude Code agent worktrees
45 + .claude/worktrees/
@@ -3551,7 +3551,7 @@
3551 3551
3552 3552 [[package]]
3553 3553 name = "makenotwork"
3554 - version = "0.6.4"
3554 + version = "0.6.5"
3555 3555 dependencies = [
3556 3556 "anyhow",
3557 3557 "argon2",
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makenotwork"
3 - version = "0.6.4"
3 + version = "0.6.5"
4 4 edition = "2024"
5 5 license-file = "LICENSE"
6 6
M wam/Cargo.lock +1 -1
@@ -1973,7 +1973,7 @@
1973 1973
1974 1974 [[package]]
1975 1975 name = "wam"
1976 - version = "0.1.0"
1976 + version = "0.2.0"
1977 1977 dependencies = [
1978 1978 "axum",
1979 1979 "chrono",
M wam/Cargo.toml +1 -1
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "wam"
3 - version = "0.1.0"
3 + version = "0.2.0"
4 4 edition = "2024"
5 5 license-file = "../LICENSE"
6 6
@@ -32,35 +32,41 @@
32 32
33 33 ### Signup → Verify → Login → Logout
34 34
35 - - [ ] `GET /join` — signup form renders
36 - - [ ] Submit signup with valid username, email, password (8+ chars)
37 - - [ ] Server logs verification email (or Postmark sends it)
38 - - [ ] Verification link in email works (`/verify-email?user=...&expires=...&sig=...`)
39 - - [ ] After verification, email_verified flag is true (check `/dashboard` details tab)
40 - - [ ] `GET /login` — login form renders
41 - - [ ] Login with correct credentials — redirects to `/dashboard`
42 - - [ ] `POST /logout` — session destroyed, redirects to `/`
43 - - [ ] Accessing `/dashboard` after logout redirects to `/login`
44 - - [ ] Login with wrong password — shows error, does not reveal whether user exists
45 - - [ ] Resend verification email works (`/api/resend-verification`)
35 + Tested against `testaccount123` (`test@makenot.work`) on 2026-05-16.
36 +
37 + - [x] `GET /join` — signup form renders
38 + - [x] Submit signup with valid username, email, password (8+ chars)
39 + - [x] Server logs verification email (or Postmark sends it) — implied by successful click below
40 + - [x] Verification link in email works (`/verify-email?user=...&expires=...&sig=...`)
41 + - [x] After verification, email_verified flag is true — confirmed in prod DB 2026-05-16 21:05 UTC
42 + - [x] `GET /login` — login form renders
43 + - [x] Login with correct credentials — redirects to `/dashboard`
44 + - [x] `POST /logout` — session destroyed, redirects to `/`
45 + - [x] Accessing `/dashboard` after logout redirects to `/login`
46 + - [x] Login with wrong password — shows error, does not reveal whether user exists (prod logs confirm `Failed login attempt` warn with `attempts` counter — no user enumeration in response)
47 + - [x] Resend verification email works (`/api/resend-verification`) — confirmed during testaccount123 signup flow
46 48
47 49 ### Account Lockout + Recovery
48 50
49 - - [ ] Fail login 5 times — account locks for 15 minutes
50 - - [ ] Lockout notification email sent with one-time login link
51 - - [ ] One-time login link works (logs you in)
52 - - [ ] One-time login link cannot be reused (single-use)
53 - - [ ] After lockout expires, normal login works again
51 + Tested against `testaccount123` on 2026-05-16 21:09 UTC.
52 +
53 + - [x] Fail login 5 times — account locks for 15 minutes (DB: `failed_login_attempts=5`, `locked_until=21:24:54`)
54 + - [x] Lockout notification email sent with one-time login link (Postmark log: subject "Security alert: Account locked")
55 + - [x] One-time login link works (logs you in) — DB cleared to `attempts=0, locked_until=NULL` after click
56 + - [x] One-time login link cannot be reused (single-use) — second click on same link rejected
57 + - [ ] After lockout expires, normal login works again — N/A (lockout cleared by OTP, not by timer); covered by normal login already verified above
54 58
55 59 ### Password Reset
56 60
57 - - [ ] `GET /forgot-password` — form renders
58 - - [ ] Submit email — reset email sent (15-minute expiry link)
59 - - [ ] Reset link loads form (`/reset-password?user=...&expires=...&sig=...`)
60 - - [ ] Submit new password — succeeds, can login with new password
61 - - [ ] Old password no longer works
62 - - [ ] Expired reset link rejected
63 - - [ ] Reusing same reset link after password change rejected (HMAC includes password hash)
61 + Tested against `testaccount123` on 2026-05-16 21:13 UTC.
62 +
63 + - [x] `GET /forgot-password` — form renders
64 + - [x] Submit email — reset email sent (15-minute expiry link)
65 + - [x] Reset link loads form (`/reset-password?user=...&expires=...&sig=...`)
66 + - [x] Submit new password — succeeds, can login with new password (breached-password advisory fired non-blocking, breach count 2,557 — working as designed)
67 + - [x] Old password no longer works
68 + - [x] Expired reset link rejected
69 + - [x] Reusing same reset link after password change rejected (HMAC includes password hash)
64 70
65 71 ### Creator Onboarding
66 72
@@ -140,10 +146,12 @@
140 146
141 147 ### Free Item Claim
142 148
143 - - [ ] As buyer, find a free item on `/discover`
144 - - [ ] `POST /api/library/add/{item_id}` — item added to library
145 - - [ ] Item content accessible
146 - - [ ] `DELETE /api/library/remove/{item_id}` — item removed from library
149 + Tested by `max` on GO (GoingsOn Desktop free item) — transaction recorded 2026-05-10.
150 +
151 + - [x] As buyer, find a free item on `/discover`
152 + - [x] `POST /api/library/add/{item_id}` — item added to library (transaction row, status=completed, amount=0)
153 + - [x] Item content accessible
154 + - [x] `DELETE /api/library/remove/{item_id}` — item removed from library
147 155
148 156 ### File Upload + Delivery
149 157
@@ -6,7 +6,9 @@
6 6
7 7 ## 🚨 LAUNCH BLOCKER — Stripe webhooks not delivering (discovered 2026-05-16)
8 8
9 - Symptom: testaccount123 completed a $5 PWYW checkout for "Audiofiles Desktop App" at 21:27 UTC. Stripe redirected to `/stripe/success` (session `cs_live_a1o3Ky7bRCXbnKNUYrGFS1JSmBFYLCxQ8zEk6gtmYfCPsyGAiJJfLNFwGm`). Transaction row is stuck `status=pending`. No item appeared in their library.
9 + **This item is consolidated into the single-sitting Stripe Dashboard knockout session at `~/Code/_meta/human_todo.md` § Stripe Dashboard Knockout Session, Step 1.** Work it from there alongside the other dashboard tasks (founder pricing Price objects, orphan Connect cleanup, Customer Portal activation, etc.) so the dashboard nav is amortized across one sitting.
10 +
11 + Symptom for context: testaccount123 completed a $5 PWYW checkout for "audiofiles Desktop App" at 2026-05-16 21:27 UTC. Stripe redirected to `/stripe/success` (session `cs_live_a1o3Ky7bRCXbnKNUYrGFS1JSmBFYLCxQ8zEk6gtmYfCPsyGAiJJfLNFwGm`). Transaction row is stuck `status=pending`. No item appeared in their library.
10 12
11 13 Root cause: Stripe is not delivering webhook events to `POST /stripe/webhook`.
12 14 - `webhook_events` table: 0 rows
@@ -14,33 +16,19 @@
14 16 - No `/stripe/webhook` hits in prod logs for past 7 days
15 17 - `STRIPE_WEBHOOK_SECRET` is set in `/opt/makenotwork/.env` — value not verified against dashboard
16 18
17 - Action items (Stripe Dashboard at https://dashboard.stripe.com/webhooks):
18 - - [ ] Confirm an endpoint exists for `https://makenot.work/stripe/webhook`
19 - - [ ] Confirm the endpoint is enabled (not disabled/paused)
20 - - [ ] Confirm live-mode toggle is on
21 - - [ ] Check "Webhook attempts" — recent attempts and their response codes (or zero attempts = endpoint missing/wrong)
22 - - [ ] Confirm signing secret matches prod `STRIPE_WEBHOOK_SECRET`
23 - - [ ] Subscribe the endpoint to at least: `checkout.session.completed`, `checkout.session.async_payment_succeeded`, `checkout.session.async_payment_failed`, `customer.subscription.created`, `customer.subscription.updated`, `customer.subscription.deleted`, `invoice.payment_succeeded`, `invoice.payment_failed`, `payment_intent.succeeded`, `payment_intent.payment_failed`, `account.updated` (Connect creators)
24 - - [ ] After fixing: use Stripe Dashboard → Events → find the testaccount123 session's `checkout.session.completed` event → "Resend" to deliver retroactively, OR manually mark the transaction completed in DB if Stripe shows the charge succeeded
25 - - [ ] Verify by triggering one more test purchase end-to-end; expect a row in `webhook_events` and the transaction to flip from `pending` to `completed`
26 -
27 19 ## External Blockers
28 20
29 21 ### Business Formation (Make Creative, LLC)
30 - - [x] D-U-N-S number — 14-501-2681, received 2026-05-09
31 - - [x] Business bank account — Mercury approved 2026-05-01
32 - - [ ] Transfer startup funds to Mercury business account
22 + All complete — see `todo_done.md`.
33 23
34 - ### Platform Accounts (D-U-N-S received — now unblocked)
24 + ### Platform Accounts
35 25
36 26 | Blocker | Status | Blocks |
37 27 |---------|--------|--------|
38 - | D-U-N-S number | 14-501-2681, received 2026-05-09 | Google Play, Microsoft Partner Center |
39 - | Google Play Developer Account ($25) | Registered 2026-05-09 | GO/BB Android builds |
40 28 | Microsoft Partner Center account | Blocked by Microsoft trust check — ref 715-123225, contact support | Windows Store distribution (optional) |
41 29 | Windows code signing certificate | Not started (individual or traditional cert — Azure Trusted Signing requires 3yr history) | GO/BB/AF Windows builds |
42 30 | OAuth Provider Registration (Fastmail) | Need to send registration info to partnerships@fastmailteam.com | GO Fastmail email OAuth |
43 - | Stripe Customer Portal activation | Dashboard → Settings → Billing → Customer portal → Activate. ~2 min, no code change. | Fan+ "Manage billing" button (deployed 2026-05-14 in MNW 0.5.18); Cancel/Resume work without this. |
31 + | Stripe Customer Portal activation | Consolidated into `_meta/human_todo.md` § Stripe Dashboard Knockout Session, Step 4. | Fan+ "Manage billing" button (deployed 2026-05-14 in MNW 0.5.18); Cancel/Resume work without this. |
44 32
45 33 ---
46 34
@@ -388,23 +376,17 @@
388 376
389 377 ### 14. SyncKit (E2E Encrypted Cloud Sync)
390 378
391 - - [x] **SyncKit auth** — OAuth2 PKCE flow tested with GO + AF on live server (2026-05-11)
392 - - [x] **Push/pull sync** — bidirectional encrypted changelog
393 - - [x] Push changes
394 - - [x] Pull changes with cursor-based pagination
379 + - [ ] **Push/pull sync** — remaining sub-items
395 380 - [ ] Table name filter for selective pull
396 381 - [ ] Idempotent push via batch_id
397 382 - [ ] **Device management** — register, list, delete devices
398 - - [x] **E2E key storage** — encrypted keys with optimistic concurrency
399 - - [x] Store key
400 - - [x] Retrieve key
383 + - [ ] **E2E key storage** — remaining sub-items
401 384 - [ ] Version conflict returns 409
402 385 - [ ] **Blob storage** — encrypted blobs with hash dedup
403 386 - [ ] Upload blob
404 387 - [ ] Download blob
405 388 - [ ] Duplicate hash skips re-upload
406 - - [x] **App management** — create apps, generate API keys
407 - - [x] Create sync app (GO + AF apps created)
389 + - [ ] **App management** — remaining sub-items
408 390 - [ ] Regenerate API key
409 391 - [ ] Link app to project/item
410 392 - [ ] Set custom slug
@@ -416,7 +398,7 @@
416 398 - [ ] Begin rotation, re-encrypt entries in batches, complete
417 399 - [ ] Verify other device can pull mixed-key entries during rotation
418 400 - [ ] Verify new device setup after rotation uses new key
419 - - [x] **SyncKit production test** — GO + AF sync tested on live server (2026-05-11). BB pending (synckit.toml needed).
401 + - [ ] **BB SyncKit production test** — needs `synckit.toml` (GO + AF complete on live server 2026-05-11; see `todo_done.md`)
420 402
421 403 ### 15. OTA Updates
422 404
@@ -477,34 +459,9 @@
477 459 - [ ] **Waitlist application** — apply to join creator waitlist
478 460 - [ ] **Invite code redemption** — use invite code during signup
479 461
480 - ### 20. Documentation Gap Checklist
462 + ### 20–21. Documentation Gap & Documented-But-Not-Implemented
481 463
482 - Features that exist in code but lack public documentation:
483 -
484 - - [x] Write guide for **git source browser** (web browsing, SSH clone, smart HTTP) — expanded git.md with HTTPS cloning, collaborators, issues, patches
485 - - [x] Write guide for **email-based issue tracker** (unique email-driven feature) — added to git.md
486 - - [x] Write guide for **email patch submission** (git send-email to MT) — added to git.md
487 - - [x] Write guide for **embed widgets** (button/card/player embeds) — new embeds.md
488 - - [x] Write guide for **media library** (dashboard feature for reusable clips) — new media-library.md
489 - - [x] Write guide for **CSV import** (bulk item creation) — new import.md
490 - - [x] Write guide for **custom profile links** (social links on profile) — expanded profile.md Links section
491 - - [x] Expand **sandbox mode** guide — already comprehensive (sandbox.md covers starting, features, limits, converting)
492 - - [x] Expand **passkey setup** guide — already detailed in security.md (setup, login, managing, 20 passkey limit)
493 - - [x] Write guide for **password reset flow** (step-by-step) — new password-reset.md
494 - - [x] Write guide for **account deactivation** (temporary vs permanent deletion) — new account-lifecycle.md
495 - - [x] Write guide for **personalized feed** (/feed page) — new feed.md
496 - - [x] Write guide for **content insertions** (pre/mid/post roll for audio) — new content-insertions.md
497 -
498 - ### 21. Documented-But-Not-Implemented Tracker
499 -
500 - Features documented in public docs that don't exist in code yet:
501 -
502 - - [ ] **Live streaming** (Everything tier, "coming soon" in docs)
503 - - [ ] **Earn-back credit program** (mentioned in FAQ)
504 - - [ ] **Content archive guarantee** (12+ month content stays live after cancel)
505 - - [ ] **HLS adaptive bitrate** (on roadmap)
506 - - [ ] **Audio transcoding** (on roadmap)
507 - - [ ] **Mobile apps** (on roadmap)
464 + Closed — see `todo_done.md`. §21 items are roadmap features documented as such; no doc revision needed pre-launch.
508 465
509 466 ### Sign-Off
510 467
@@ -554,12 +511,7 @@
554 511
555 512 - [ ] Phase 22E: MediaMTX deployment on alpha-west-1 (install binary, systemd unit, Caddy config, Cloudflare DNS, firewall rules)
556 513 - [ ] Add `ffprobe` to production server (Phase 14E-1)
557 - - [x] Generate Tauri signing keys — per-app keys at `~/.tauri/goingson.key{,.pub}` and `~/.tauri/balanced-breakfast.key{,.pub}` (AF is not a Tauri app). BB key rotated 2026-05-16 (original password unrecoverable; no shipped BB binaries with old pubkey)
558 - - [x] Add public keys to `tauri.conf.json` — GO and BB both wired with `plugins.updater.pubkey` + endpoint `https://makenot.work/api/v1/sync/ota/{app}/{{target}}/{{arch}}/{{current_version}}`
559 - - [x] Enable `bundle.createUpdaterArtifacts: true` in both apps' `tauri.conf.json` — Tauri 2 requires opt-in; without it builds skip the updater bundles + `.sig` sidecars silently
560 - - [x] Deploy private keys to astra + windows-x86; password file `~/.tauri/passwords.env` (Linux) / `passwords.ps1` (Windows). Master copy at `_private/tauri-passwords.env`
561 514 - [ ] Deploy private keys to pop-os (offline 2026-05-14, last seen 2d ago — sync when next online)
562 - - [x] Verify signed build produces `.sig` sidecars — confirmed on astra for BB 0.3.3 (AppImage, deb, rpm all signed)
563 515 - [ ] Full end-to-end OTA flow: build signed GO release, upload artifact via MNW release management UI, install on clean machine, confirm `/api/v1/sync/ota/...` returns 200 and Tauri updater accepts the signature
564 516 - [ ] Set S3 lifecycle rule on the upload prefix: delete incomplete/unconfirmed objects after 36 hours (safety net for presigned URL cleanup)
565 517
M server/docs/todo.md +241 -375
Binary file