diff --git a/README.md b/README.md index d7a15dc..c23d942 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,12 @@ persists across reloads. Every design surface participates in the same Nostr-backed community feed. -- **Identity** via NIP-07 (Alby, nos2x, etc.). +- **Identity** via NIP-07 (Alby, nos2x, etc.). The Login button opens a + picker — NIP-07 today, NIP-46 remote signer and raw `nsec` paste + reserved as future options. Once signed in, the Nostr widget becomes + a dropdown with **View Profile**, **Settings**, and **Logout**. +- **Settings modal** — the per-relay list, the WoT trust filters, the + NWC wallet connection, and the block-list management all live here. - **Templates and designs** publish as kind-30078 parameterized replaceable events tagged `casewrap-`, with the `d`-tag mode-prefixed so cover/disc/jewel/custom-art/disc-design designs for the same title don't collide. - **Community modal** browses New / Popular / Zapped / Search / My Designs with category and language filters, plus optional WoT trust filters when signed in. - **Profile pages** at `/u/` show the author's banner, avatar, NIP-05, npub (copyable), about, Lightning address, and the grid of their published designs. Profile state is cached per session. @@ -116,13 +121,26 @@ Every design surface participates in the same Nostr-backed community feed. ## Lightning -Two flavors of Lightning are wired in: +Three flavors of Lightning are wired in: - **Tips** — pure LNURL-pay, no NWC required. Pick an amount (21 / 100 / 500 / 1k / 5k / 21k / Custom), the recipient's `lud16` or `lud06` resolves to an LNURL-pay endpoint, and you get a bolt11 invoice + QR + lightning: deep-link. If the recipient's wallet supports zap requests (`allowsNostr: true`), we also sign a NIP-57 kind-9734 zap request and pass it along, so a kind-9735 receipt lands on relays after settlement. +- **NWC (NIP-47) wallet** — paste a `nostr+walletconnect://…` URI under Settings and Artstr can sign + send `pay_invoice` requests directly to your wallet (CoinOS-first onboarding, but any NWC-compatible wallet works). NWC powers one-click tips, premium unlocks, and the split-zap legs. The URI is **synced across logins** as an encrypted kind-30078 note keyed to your pubkey, so a new browser only needs your NIP-07 extension to reconnect the wallet. - **Tracked zaps** — kind-9735 receipts feed a per-event aggregate, surfaced as `⚡ ` on feed cards / previews / profile pages, and as a sortable **Zapped** tab in the Community modal. - **WebLN auto-pay** is offered as a one-click button when an extension is detected. - **Payment detection** — after a tracked invoice is issued, a poll watches for the receipt and auto-closes the tip modal when payment is confirmed. +## Premium encrypted designs + +Creators can publish paid templates. The publish modal exposes a **Premium encrypted** toggle that requires a sat amount and a short "soft-gate, not strong DRM" acknowledgment. + +- **Static soft-gate.** The payload is AES-256-GCM encrypted in the browser with a key derived via HKDF-SHA256 from public event material plus an obfuscated per-epoch pepper baked into the static client. There is no server and no creator-online step. Honest framing: this raises friction against drive-by scraping but a determined reverse-engineer can recover the client pepper. Stronger DRM can swap in later without changing the buyer-side vault. +- **Watermarked preview.** A low-resolution JPEG of the design is rendered pre-encrypt and embedded in the envelope, so the community browser still has something to show. +- **Split-zap platform fee.** Every unlock is a Lightning split — creator 70 %, platform 30 % — both legs fired in parallel over NWC, with the platform leg's `lud16` resolved dynamically from the platform pubkey's kind-0 so it can change without a code release. +- **Purchase vault.** Once both receipts confirm, Artstr derives the key locally, decrypts in place, and records the unlock in a NIP-44 self-encrypted kind-30078 vault (`d=artstr:purchase-vault:v1`). The vault auto-splits into per-item events when over 40 KB. A fresh browser hydrates the vault on Nostr login (toast: "Restored N unlocks ✓"). Edit-in-place is address-tolerant, so re-publishing a premium design doesn't invalidate prior unlocks. +- **Premium browser tab.** New ⚡ **Premium** tab in the community modal lists encrypted designs; cards get a gradient stroke + PREMIUM ribbon. The **My Designs → Premium** sub-tab lists everything you've unlocked. + +Spec lives in `docs/PREMIUM_DESIGNS_FEATURE.md`. + ## Save, share, restore - **Save project** writes the design (with metadata) to a JSON file. @@ -147,7 +165,7 @@ Two flavors of Lightning are wired in: - `src/index.html` — the complete single-file app. Open it directly in a browser, or serve it from any static host. Vercel rewrites in `vercel.json` map `/share/:id` and `/u/:npub` to the SPA entry. - `src/vendor/qrcode.min.js` — vendored QR encoder (used for Lightning tip invoices). The GIF89a encoder for pixel-art animation export is implemented inline in `index.html`. -- `docs/` — feature specs. `PEN_TOOL_FEATURE.md` covers the shipped pen / pencil / vector tooling; `SLIDE_DECK_FEATURE.md` covers the shipped slide / deck / presenter system (Phases A–D; dual-window presenter is future); `PIXEL_ART_FEATURE.md` covers the shipped palette-indexed pixel-art system (Phases A–D). Badges, collections, NWC zaps, zap-gated templates, private publishing, and Stacks are still unbuilt. +- `docs/` — feature specs. `PEN_TOOL_FEATURE.md` covers the shipped pen / pencil / vector tooling; `SLIDE_DECK_FEATURE.md` covers the shipped slide / deck / presenter system (Phases A–D; dual-window presenter is future); `PIXEL_ART_FEATURE.md` covers the shipped palette-indexed pixel-art system (Phases A–D); `PREMIUM_DESIGNS_FEATURE.md` covers the shipped premium-encrypted-designs system (NWC split-zap + soft-gate + purchase vault); the older `ZAP_GATED_PREMIUM_FEATURE.md` / `ZAP_GATED_TEMPLATES_FEATURE.md` / `ZAPS_NWC_FEATURE.md` carry "superseded" banners and remain for history. Badges, collections, private publishing (Phases 3–4), and Stacks are still unbuilt. - `TODO.md` — running list of deferred work and cleanup items. ## Schema diff --git a/TODO.md b/TODO.md index 1e78d6c..86bd14d 100644 --- a/TODO.md +++ b/TODO.md @@ -66,29 +66,32 @@ toggle that fits the early-web aesthetic. Add new editor-UX items below. Each has a full spec in `docs/`. -- **Premium encrypted designs (static soft-gate + purchase vault)** — - `docs/PREMIUM_DESIGNS_FEATURE.md`. **In-progress / current focus.** - Creators publish encrypted designs gated by a Lightning split zap - (creator 70% / platform 30%). Buyers unlock via NWC; the static - client derives the AES key locally after valid split-zap receipts - arrive on relays, decrypts the payload, and stores the key in a - NIP-44 self-encrypted purchase vault for cross-device re-open. - Honest "soft gate, not strong DRM" framing — determined reverse- - engineers can still extract the client pepper; the protection is - against casual copying / relay scraping. - Foundation already shipped: noble crypto bundle, NWC client + - wallet settings, platform-fee dual-zap orchestrator, NWC-default - Lightning tips, and a tag-only gate UI (still in place but now - superseded by the encrypted content envelope). See - `docs/ZAP_GATED_PREMIUM_FEATURE.md` for the Phases 0–3 history. - **Artstr Stacks** — `docs/STACKS_FEATURE.md`. Interactive fullscreen page/card stacks (HyperCard for Nostr) — the Slide Deck extended with - layer actions and an interactive viewer. Queued after zap-gated lands. + layer actions and an interactive viewer. - **Badges (NIP-58)** — `docs/BADGES_FEATURE.md`. Award / display Nostr badges on profile pages. - **Collections (NIP-51 sets)** — `docs/COLLECTIONS_FEATURE.md`. Let users organize favorite community templates into named sets. +## Premium-templates polish + +The premium-encrypted-designs arc shipped in 2026-05; see +`docs/PREMIUM_DESIGNS_FEATURE.md` for the canonical spec. Open +follow-ups worth their own work: + +- **Phase 4 E2E test matrix** — real-money round-trip through CoinOS: + publish premium → unlock from another browser → vault sync. Plus + the edge-case matrix from §19 item 4 of the spec (wallet budget + exhausted, platform fail after creator paid, partial-pay resume, + missing lud16, cache wipe → relay fast-path). +- **Confirm()-style modals** — the unlock confirm and a few other + premium-related prompts still use native `confirm()`. Replace with + the styled in-app modal pattern. +- **Future-proofing** — when an epoch's soft-gate pepper gets reverse- + engineered we'll ship a new epoch. The infra is in place; the + rotation playbook should land as a SECURITY.md when we do it. + ## Phase-3+ work on shipped features - **Private (encrypted) publishing — Phases 3 & 4.** @@ -100,6 +103,33 @@ Each has a full spec in `docs/`. ## Shipped (recent) +- **Premium encrypted designs — static soft-gate + NWC split-zap + + purchase vault.** Spec lives in `docs/PREMIUM_DESIGNS_FEATURE.md`. + Creators tick "Premium encrypted" + a soft-gate ack in the publish + modal, set a minimum sat amount; we AES-256-GCM encrypt the + payload (HKDF over an obfuscated per-epoch pepper + per-design + salt + the event coordinate as AAD), render a watermarked low-res + JPEG preview embedded in the envelope, and emit the §5.1 tag set + with two zap-split tags (creator 70 % / platform 30 %). + Consumers see a gradient-stroked card + ⚡ PREMIUM ribbon with an + "Unlock for N sats" CTA on all three import paths (feed card, + preview pane Use/Fork, preview pane Save JSON). Unlock fires both + pay_invoice legs in parallel over NWC, derives the soft-gate key + locally on receipt confirmation, decrypts in place with a reveal + animation. Cross-device sync via a NIP-44 self-encrypted purchase + vault (kind-30078 `d=artstr:purchase-vault:v1`) that auto-splits + into per-item events when over 40 KB. Address-tolerant unlock + lookup so edit-in-place doesn't invalidate prior purchases. + Hydrates on Nostr login with a "Restored N unlocks ✓" toast. + Soft-gate framing is honest in every UI surface: it raises + friction against drive-by scraping, NOT strong DRM. Foundation + layers (noble bundle, NWC client + wallet settings UI with + CoinOS-first onboarding, platform-fee dual-zap orchestrator, NWC- + default Lightning tips, login-method picker, profile dropdown + menu with View Profile / Settings / Logout, the Settings modal + itself, the new Premium tab + mobile-friendly browser layout) + all shipped as part of the same arc. ~30 commits on the + `zap-gated` branch, merged into main 2026-05. - **Pixel-art dropdowns — no more sidebar clipping.** The pixel-editor resize-grid and PNG-export menus were `position: absolute; right: 0` inside their toolbar wrap. When the toolbar wrapped and the trigger diff --git a/docs/PREMIUM_DESIGNS_FEATURE.md b/docs/PREMIUM_DESIGNS_FEATURE.md index 45954b7..5eb0466 100644 --- a/docs/PREMIUM_DESIGNS_FEATURE.md +++ b/docs/PREMIUM_DESIGNS_FEATURE.md @@ -4,19 +4,46 @@ ### Status -Canonical spec for the encryption + key-delivery layer of premium templates. -This supersedes the Phase 5/6 sketch in `ZAP_GATED_PREMIUM_FEATURE.md`, -which described a creator-online NIP-04 DM key-delivery scheme. That -approach is abandoned in favour of the **static soft-gate + buyer -purchase vault** model below, which removes the creator-online -requirement entirely. +**Shipped on `zap-gated`, merged into `main` 2026-05-29.** This is the +canonical spec for the encryption + key-delivery layer of premium +templates. It supersedes the Phase 5/6 sketch in +`ZAP_GATED_PREMIUM_FEATURE.md`, which described a creator-online +NIP-04 DM key-delivery scheme. That approach was abandoned in favour +of the **static soft-gate + buyer purchase vault** model below, which +removes the creator-online requirement entirely. + +Implementation maps to §10 of this doc: + +- **Step 0 — Crypto bundle.** `src/noble-bundle.min.js` exposes + `@noble/secp256k1` v3.1.0 + `@noble/hashes` v2.2.0 as + `window.ArtstrNoble`. +- **Step 1 — Soft-gate primitive.** The `Premium` IIFE in + `src/index.html` (`pepperBytesForEpoch`, `deriveKey`, + `encryptPayload`, `decryptPayload`). +- **Step 2 — Watermarked preview pipeline.** Canvas-based JPEG + renderer that snapshots a low-res preview of the design pre-encrypt + and embeds it in the envelope's `preview.dataUrl`. +- **Step 3 — Encrypted publish + premium consume.** Publish modal + premium controls + soft-gate ack, encrypted event emission with the + §5.1 tag set, and a feed/preview consume path that shows the + gradient-stroked card, ⚡ PREMIUM ribbon, and "Unlock for N sats" CTA + on the three import paths (feed card, preview Use/Fork, preview + Save JSON). +- **Step 4 — Purchase vault + My Purchases tab.** NIP-44 self- + encrypted kind-30078 vault (`d=artstr:purchase-vault:v1`), auto- + splitting into per-item events (`d=artstr:purchase:`) + when the manifest crosses 40 KB. Hydrates on login with a + "Restored N unlocks ✓" toast. The Premium tab in My Designs lists + purchased items address-tolerantly so an edit-in-place doesn't + invalidate a prior unlock. Phases 0–3 of `ZAP_GATED_PREMIUM_FEATURE.md` (the noble bundle, NWC -client, platform-fee plumbing, and the existing tag-only UI) are -already shipped on the `zap-gated` branch and are reused unchanged -here. The remaining work is the soft-gate crypto, the encrypted -event format, the watermarked preview pipeline, and the purchase -vault. +client, platform-fee plumbing, and the original tag-only UI) shipped +earlier on the same branch and were reused for the encrypted version. + +Phase 4 (the real-money E2E test matrix from §19 item 4) is the only +open work and now lives under "Premium-templates polish" in +`TODO.md`. ### Goal