Skip to main content

max / makenotwork

Sprints 7-9: collections, discovery, docs, UI examples Sprint 7 — Collections Everywhere: - Shared collections.js picker (item page, discover cards, library) - "Saved (N)" button state with toast feedback - Save buttons on discover list/grid views (auth-gated) Sprint 8 — Discovery Improvements: - AI tier filter in discover sidebar with facet counts - Search suggestions/autocomplete (tags, projects, creators) - "Has source code" checkbox filter for projects - User download tracking (migration 100) with "New" badge in library Sprint 9 — Documentation: - Updated 6 doc files against feature map: collections, promo codes, git, license keys, SyncKit, FAQ - Fixed wrong limits, added missing features, expanded FAQ by role DocEngine [!UI] directive: - New directive converts > [!UI] name to placeholder figure elements - Doc loader resolves placeholders from site-docs/examples/*.html - Proof of concept: discover-filters and collection-picker examples - CSS: .doc-ui frame with pointer-events:none and figcaption Audit remediations: - Fixed XSS in search suggestion category (unescaped innerHTML) - Fixed XSS in collection picker (inline onsubmit → addEventListener) - Fixed a11y: span onclick → button with aria-label on discover cards - Removed unused import (cart.rs) and dead code (app_sync.rs) - 0 warnings
Co-Authored-By
Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-08 18:32 UTC
Commit: 942a6c1a53cb7c3aeb4a5df02b5a0f4b728327bc
Parent: 67b770c
37 files changed, +1303 insertions, -305 deletions
@@ -3445,7 +3445,7 @@
3445 3445
3446 3446 [[package]]
3447 3447 name = "makenotwork"
3448 - version = "0.5.0"
3448 + version = "0.5.6"
3449 3449 dependencies = [
3450 3450 "anyhow",
3451 3451 "argon2",
@@ -1,92 +1,29 @@
1 1 # Makenotwork TODO
2 2
3 3 ## Status
4 - v0.5.0 deployed 2026-05-06. Soft launch target 2026-05-09. Audit grade A. ~85K LOC, 1,912 tests, 0 warnings. Migration 096.
4 + v0.5.0 deployed 2026-05-06. Soft launch target 2026-05-09. Audit grade A. ~85K LOC, 1,912 tests, 0 warnings (verified). Migration 100. Sprints 1-9 complete (see `todo_done.md`).
5 5
6 6 Human tasks in `human_todo.md`. Completed items in `todo_done.md`.
7 7
8 8 ---
9 9
10 - ## Sprint 1: Creator Self-Service (table stakes)
10 + ## Deferred from Sprints
11 11
12 - Creators expect these from any platform. Without them, sellers hit walls during normal operation.
12 + - [ ] Add bulk rename operation (Sprint 2)
13 + - [ ] Add global search across all projects and items from dashboard (Sprint 2)
14 + - Deferred: onboarding checklist persistence, banner for unsubscribed creators (Sprint 4, low urgency during alpha)
15 + - Deferred: real-time pricing validation (Sprint 6, low value — server validates on save)
13 16
14 - - [x] Add refund initiation from item sales tab (already implemented — refund button + Stripe refund + webhook handler)
15 - - [x] Allow editing promo codes after creation (PUT endpoint, inline edit form for max_uses, starts_at, expires_at)
16 - - [x] Add bulk delete for expired promo codes (DELETE /api/promo-codes/expired + "Delete all expired" button)
17 - - [x] Add scheduled start/end dates for promo codes (migration 099: starts_at column, validation at all checkout paths)
18 - - [x] Add purchase receipt/invoice download for completed purchases (GET /receipt/{transaction_id}, linked from library)
19 - - [x] Handle mid-queue cart checkout failure gracefully (redirect to /cart?checkout=partial with banner)
17 + ---
20 18
21 - ## Sprint 2: Catalog Power Tools
19 + ## Audit Remediations (2026-05-08, post-Sprint 9)
22 20
23 - Creators with 20+ items need these. One-at-a-time editing doesn't scale.
24 -
25 - - [x] Always show bulk action bar (disabled/grayed until items selected, enables on checkbox)
26 - - [ ] Add bulk rename operation
27 - - [x] Add bulk tag operation (find-or-create tag, bulk INSERT ON CONFLICT)
28 - - [x] Add bulk price change operation (inline form with dollar input)
29 - - [x] Implement soft delete with 7-day recovery — "Recently Deleted" collapsible with restore buttons
30 - - [x] Bulk delete now soft-deletes (sets deleted_at + is_public=false, scheduler purges after 7 days)
31 - - [ ] Add global search across all projects and items from dashboard
32 -
33 - ## Sprint 3: Onboarding Overhaul — DONE
34 -
35 - Join wizard collapsed from 5 steps to 3 (Account, Profile, Welcome). Pitch and Stripe removed from wizard — pitch lives on dashboard Creator Plan tab, Stripe on Payments tab. Welcome page branches by intent: "Browse and buy" vs "I want to sell" with contextual CTAs for invited users and existing creators.
36 -
37 - ## Sprint 4: Dashboard Polish — DONE
38 -
39 - - [x] Rename "creator tiers" to "Creator Plans" (user_creator.html, dashboard-user.html, creators.html)
40 - - [x] Show tier limits inline on Creator Plan tab (storage usage + link to plan docs)
41 - - [x] Hide "good standing" noise — Account Status section hidden when no moderation actions
42 - - [x] Export link already visible in dashboard header (line 78)
43 - - [x] Add section headers to "More" dropdown (Content, Integration, Support)
44 - - [x] "Explore Your Project Tools" discovery card in project overview (6 feature cards in collapsible)
45 - - Deferred: onboarding checklist persistence, banner for unsubscribed creators (low urgency during alpha)
46 -
47 - ## Sprint 5: Account Settings Cleanup — DONE
48 -
49 - Reordered: Account Status (top, only shown when moderation active) → Security (checklist + password/2FA/passkeys/sessions) → Account (email/username) → Preferences → Data → Account Management. Added security checklist card. Differentiated pause vs delete with inline guidance. Linked SSH Keys from project Code tab. Stripe Tax toggle stays in Payments (natural home, not worth moving).
50 -
51 - ## Sprint 6: Item Editor Refinements — DONE
52 -
53 - - [x] Move Sections management to collapsible details (auto-open when sections exist)
54 - - [x] Add tip/callout about Sections (explanation + suggested section names in empty state)
55 - - [x] Pricing strategy guide at top of pricing tab (fixed, PWYW, free+codes, license keys)
56 - - [x] Clarified PWYW + license keys compatibility in license key description
57 - - [x] Item type descriptions already render (audit false negative — type_card_desc in wizard)
58 - - [x] File type hints already shown (MP3/WAV/FLAC/OGG/AAC for audio, MP4/WebM/MOV for video)
59 - - [x] Tier-specific file size limit already validated client-side with upgrade message
60 - - Deferred: real-time pricing validation (low value — server validates on save)
61 -
62 - ## Sprint 7: Collections Everywhere
63 -
64 - Collections exist but are hard to find and use. This makes them a first-class feature.
65 -
66 - - [ ] Improve "Add to Collection" affordance on item page
67 - - [ ] Add "Add to Collection" action on discover result cards
68 - - [ ] Add "Add to Collection" from library items
69 -
70 - ## Sprint 8: Discovery Improvements
71 -
72 - Help fans find content and help creators understand their audience.
73 -
74 - - [ ] Expose AI Tier filter in discover UI
75 - - [ ] Add search suggestions/autocomplete
76 - - [ ] Add "Has source code" filter for projects with linked Git repos
77 - - [ ] Add download count analytics per item
78 - - [ ] Add distinction between "already downloaded" and "available for download" in library
79 -
80 - ## Sprint 9: Documentation
81 -
82 - Fill gaps so creators can self-serve instead of contacting support.
83 -
84 - - [ ] Add docs for Collections feature
85 - - [ ] Add docs for Promo Codes & Discounts
86 - - [ ] Add docs for Git integration / source browser
87 - - [ ] Add docs for License Keys
88 - - [ ] Add docs for SyncKit integration
89 - - [ ] Add FAQ / Troubleshooting page by user role
21 + - [x] Fix XSS: escape `s.category` and `s.url` in search suggestions innerHTML (discover.html)
22 + - [x] Fix XSS: replace inline `onsubmit` handler with `addEventListener` in collections.js
23 + - [x] Fix a11y: convert `<span onclick>` save buttons to `<button>` with `aria-label` on discover cards
24 + - [ ] Performance: consider rewriting double-nested correlated subquery in `get_user_purchases` (has_new_version) to use LEFT JOIN or CTE
25 + - [x] Remove unused import `spawn_email` in `stripe/checkout/cart.rs`
26 + - [x] Remove dead code `update_app_sync_sub_tier` in `db/app_sync.rs`
90 27
91 28 ---
92 29
@@ -254,3 +254,80 @@
254 254 ## Integration Test Fixes (2026-05-02)
255 255
256 256 All 34 previously-failing tests resolved. Key changes: auth rate limiter per-handler, advisory lock deadlock fix, unique IP per TestClient, fast-tests feature flag, sandbox test consolidation.
257 +
258 + ---
259 +
260 + ## Sprint 1: Creator Self-Service (2026-05-06)
261 +
262 + - [x] Add refund initiation from item sales tab (already implemented — refund button + Stripe refund + webhook handler)
263 + - [x] Allow editing promo codes after creation (PUT endpoint, inline edit form for max_uses, starts_at, expires_at)
264 + - [x] Add bulk delete for expired promo codes (DELETE /api/promo-codes/expired + "Delete all expired" button)
265 + - [x] Add scheduled start/end dates for promo codes (migration 099: starts_at column, validation at all checkout paths)
266 + - [x] Add purchase receipt/invoice download for completed purchases (GET /receipt/{transaction_id}, linked from library)
267 + - [x] Handle mid-queue cart checkout failure gracefully (redirect to /cart?checkout=partial with banner)
268 +
269 + ---
270 +
271 + ## Sprint 3: Onboarding Overhaul (2026-05-06)
272 +
273 + Join wizard collapsed from 5 steps to 3 (Account, Profile, Welcome). Pitch and Stripe removed from wizard — pitch lives on dashboard Creator Plan tab, Stripe on Payments tab. Welcome page branches by intent: "Browse and buy" vs "I want to sell" with contextual CTAs for invited users and existing creators.
274 +
275 + ---
276 +
277 + ## Sprint 4: Dashboard Polish (2026-05-06)
278 +
279 + - [x] Rename "creator tiers" to "Creator Plans" (user_creator.html, dashboard-user.html, creators.html)
280 + - [x] Show tier limits inline on Creator Plan tab (storage usage + link to plan docs)
281 + - [x] Hide "good standing" noise — Account Status section hidden when no moderation actions
282 + - [x] Export link already visible in dashboard header (line 78)
283 + - [x] Add section headers to "More" dropdown (Content, Integration, Support)
284 + - [x] "Explore Your Project Tools" discovery card in project overview (6 feature cards in collapsible)
285 +
286 + ---
287 +
288 + ## Sprint 5: Account Settings Cleanup (2026-05-06)
289 +
290 + Reordered: Account Status (top, only shown when moderation active) → Security (checklist + password/2FA/passkeys/sessions) → Account (email/username) → Preferences → Data → Account Management. Added security checklist card. Differentiated pause vs delete with inline guidance. Linked SSH Keys from project Code tab.
291 +
292 + ---
293 +
294 + ## Sprint 6: Item Editor Refinements (2026-05-06)
295 +
296 + - [x] Move Sections management to collapsible details (auto-open when sections exist)
297 + - [x] Add tip/callout about Sections (explanation + suggested section names in empty state)
298 + - [x] Pricing strategy guide at top of pricing tab (fixed, PWYW, free+codes, license keys)
299 + - [x] Clarified PWYW + license keys compatibility in license key description
300 + - [x] Item type descriptions already render (audit false negative — type_card_desc in wizard)
301 + - [x] File type hints already shown (MP3/WAV/FLAC/OGG/AAC for audio, MP4/WebM/MOV for video)
302 + - [x] Tier-specific file size limit already validated client-side with upgrade message
303 +
304 + ---
305 +
306 + ## Sprint 7: Collections Everywhere (2026-05-07)
307 +
308 + - [x] Improve "Add to Collection" affordance on item page (saved state button, toast feedback, shared collections.js)
309 + - [x] Add "Add to Collection" action on discover result cards (list + grid views, auth-gated)
310 + - [x] Add "Add to Collection" from library items (shared picker with inline creation)
311 +
312 + ---
313 +
314 + ## Sprint 8: Discovery Improvements (2026-05-07)
315 +
316 + - [x] Expose AI Tier filter in discover UI (sidebar facet with counts, hidden input sync)
317 + - [x] Add search suggestions/autocomplete (combined tags/projects/creators endpoint, keyboard nav dropdown)
318 + - [x] Add "Has source code" filter for projects with linked Git repos (checkbox, EXISTS subquery)
319 + - [x] Add download count analytics per item (already implemented — per-version in Files tab, total in analytics)
320 + - [x] Add distinction between "already downloaded" and "available for download" in library (migration 100, user_downloads table, "New" badge)
321 +
322 + ---
323 +
324 + ## Sprint 9: Documentation (2026-05-08)
325 +
326 + All 6 docs updated with feature map cross-reference after /map-features audit.
327 +
328 + - [x] Collections docs — fixed limits 50/200, added discover/library save points, saved state
329 + - [x] Promo Codes docs — added editing, starts_at, bulk delete expired
330 + - [x] Git docs — added raw file access, ref selector, README rendering
331 + - [x] License Keys docs — added offline verify endpoint, license.txt, revocation, PWYW, /api/v1/ prefix
332 + - [x] SyncKit docs — added SSE, key rotation, subscription gating, batch_id, sync status
333 + - [x] FAQ — added For Developers section, tier features, custom domains, data retention, content moderation
@@ -185,6 +185,7 @@
185 185 ],
186 186 link_prefix: "/docs".to_string(),
187 187 unpublished_pattern: Some("unpublished/".to_string()),
188 + examples_path: Some(std::path::Path::new(&docs_path).join("../examples").into()),
188 189 },
189 190 ));
190 191
@@ -3941,6 +3941,9 @@
3941 3941 .col-right { text-align: right; }
3942 3942 .results-table { border: 1px solid var(--border); border-top: none; }
3943 3943 .table-row { display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: 0.5rem; padding: 0.4rem 0.75rem; align-items: center; text-decoration: none; color: var(--detail); font-size: 0.85rem; border-bottom: 1px solid var(--border); transition: background 0.1s ease; }
3944 + .table-row-item { grid-template-columns: 1fr 30px; padding: 0; gap: 0; }
3945 + .table-row-item .table-row-link { display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: 0.5rem; padding: 0.4rem 0.75rem; align-items: center; text-decoration: none; color: inherit; flex: 1; }
3946 + .table-row-item .row-save { display: flex; align-items: center; justify-content: center; }
3944 3947 .table-row.project-row { grid-template-columns: 1fr 100px 80px 70px; }
3945 3948 .table-row:last-child { border-bottom: none; }
3946 3949 .table-row:nth-child(odd) { background: var(--light-background); }
@@ -3994,6 +3997,8 @@
3994 3997 .discover-sidebar { display: none; }
3995 3998 .discover-sidebar.show { display: block; margin-bottom: 1rem; }
3996 3999 .table-header, .table-row { grid-template-columns: 40px 1fr 60px; }
4000 + .table-row-item { grid-template-columns: 1fr 30px; }
4001 + .table-row-item .table-row-link { grid-template-columns: 40px 1fr 60px; }
3997 4002 .table-header.projects-header, .table-row.project-row { grid-template-columns: 1fr 70px; }
3998 4003 .row-date, .row-items, .row-category { display: none; }
3999 4004 .table-header span:nth-child(3), .table-header span:nth-child(4), .table-header span:nth-child(5) { display: none; }
@@ -4002,6 +4007,8 @@
4002 4007
4003 4008 @media (max-width: 480px) {
4004 4009 .table-header, .table-row { grid-template-columns: 1fr 60px; }
4010 + .table-row-item { grid-template-columns: 1fr 30px; }
4011 + .table-row-item .table-row-link { grid-template-columns: 1fr 60px; }
4005 4012 .row-type { display: none; }
4006 4013 .table-header span:first-child { display: none; }
4007 4014 .table-header.projects-header, .table-row.project-row { grid-template-columns: 1fr; }
@@ -4190,3 +4197,88 @@
4190 4197 .tip-submit:hover {
4191 4198 opacity: 0.85;
4192 4199 }
4200 +
4201 + /* ===========================================
4202 + COLLECTION PICKER (shared dropdown)
4203 + =========================================== */
4204 +
4205 + .collection-picker-anchor { position: relative; }
4206 + .collection-picker {
4207 + position: absolute; left: 0; right: 0; top: 100%; z-index: 50;
4208 + background: var(--background); border: 1px solid var(--border);
4209 + box-shadow: 0 2px 8px rgba(0,0,0,0.12); min-width: 220px;
4210 + }
4211 + .collection-picker-list { max-height: 200px; overflow-y: auto; padding: 0.25rem 0; }
4212 + .collection-picker-item {
4213 + display: flex; align-items: center; gap: 0.5rem;
4214 + padding: 0.4rem 0.75rem; cursor: pointer; font-size: 0.9rem;
4215 + }
4216 + .collection-picker-item:hover { background: var(--surface-muted); }
4217 + .collection-picker-loading,
4218 + .collection-picker-empty { padding: 0.5rem 0.75rem; opacity: 0.6; font-size: 0.85rem; }
4219 + .collection-picker-create { border-top: 1px solid var(--border); padding: 0.5rem 0.75rem; }
4220 + .collection-picker-create form { display: flex; gap: 0.5rem; }
4221 + .collection-picker-create input { flex: 1; padding: 0.3rem 0.5rem; font-size: 0.85rem; min-width: 0; }
4222 + .collection-picker-create button { font-size: 0.85rem; white-space: nowrap; }
4223 +
4224 + /* Save button on discover cards */
4225 + .row-save, .grid-card-save {
4226 + background: none; border: none; cursor: pointer;
4227 + font-size: 0.85rem; padding: 0.2rem 0.4rem; opacity: 0.4;
4228 + color: var(--detail); transition: opacity 0.15s;
4229 + }
4230 + .row-save:hover, .grid-card-save:hover { opacity: 1; }
4231 + .grid-card-save {
4232 + position: absolute; top: 0.4rem; right: 0.4rem; z-index: 2;
4233 + background: var(--background); border-radius: 3px; padding: 0.25rem 0.4rem;
4234 + box-shadow: 0 1px 3px rgba(0,0,0,0.15); opacity: 0;
4235 + }
4236 + .grid-card:hover .grid-card-save { opacity: 0.7; }
4237 + .grid-card-save:hover { opacity: 1; }
4238 +
4239 + /* Item page save button saved state */
4240 + button.saved { border-color: var(--accent); color: var(--accent); }
4241 +
4242 + /* ===========================================
4243 + SEARCH SUGGESTIONS
4244 + =========================================== */
4245 +
4246 + .search-wrapper { position: relative; flex: 1; min-width: 0; }
4247 + .search-suggestions {
4248 + display: none; position: absolute; left: 0; right: 0; top: 100%; z-index: 50;
4249 + background: var(--background); border: 1px solid var(--border); border-top: none;
4250 + box-shadow: 0 4px 12px rgba(0,0,0,0.1); max-height: 280px; overflow-y: auto;
4251 + }
4252 + .suggestion-item {
4253 + display: flex; justify-content: space-between; align-items: center;
4254 + padding: 0.5rem 0.75rem; text-decoration: none; color: var(--detail);
4255 + font-size: 0.85rem; cursor: pointer;
4256 + }
4257 + .suggestion-item:hover, .suggestion-item.highlighted { background: var(--surface-muted); }
4258 + .suggestion-category { font-size: 0.75rem; opacity: 0.5; text-transform: uppercase; letter-spacing: 0.05em; }
4259 +
4260 + /* ===========================================
4261 + DOC UI EXAMPLES (embedded live UI in docs)
4262 + =========================================== */
4263 +
4264 + .doc-ui {
4265 + margin: 1.5rem 0; border: 1px solid var(--border); border-radius: 4px; overflow: hidden;
4266 + }
4267 + .doc-ui-frame {
4268 + padding: 1rem; background: var(--light-background); pointer-events: none; user-select: none;
4269 + }
4270 + .doc-ui figcaption {
4271 + padding: 0.5rem 1rem; font-size: 0.8rem; opacity: 0.6;
4272 + border-top: 1px solid var(--border); background: var(--surface-alt);
4273 + font-family: var(--font-mono);
4274 + }
4275 + .doc-ui-missing {
4276 + padding: 1rem; opacity: 0.4; font-style: italic;
4277 + }
4278 +
4279 + /* Library "New" badge for items with undownloaded versions */
4280 + .badge-new {
4281 + background: var(--accent); color: #fff; font-size: 0.7rem;
4282 + padding: 0.1rem 0.35rem; border-radius: 3px; margin-left: 0.4rem;
4283 + vertical-align: middle; font-weight: bold;
4284 + }
@@ -36,6 +36,7 @@
36 36 <div id="notifications" class="toast-container" role="alert" aria-live="polite"></div>
37 37
38 38 <script src="/static/mnw.js"></script>
39 + <script src="/static/collections.js"></script>
39 40 {% block scripts %}{% endblock %}
40 41 </body>
41 42 </html>