Phase 1 — publish a design encrypted, readable only by the author:
- Crypto helpers: encryptProjectEnvelope / decryptProjectEnvelope —
AES-256-GCM over gzipped JSON, AES key NIP-44 key-wrapped to the
author (NIP-04 fallback), via a nostrEncryptCapability() probe. All
in-browser, no new dependencies.
- publishEncryptedDesign: a feed-invisible kind:30078 event — random
persistent d-tag, only d / alt / encrypted tags, no casewrap tag.
- Publish-confirm modal gains a Public / Private control with the
privacy warning and a capability gate; wired into the template and
disc-design publish paths.
- My Designs decrypts the author's own private events and shows a
lock badge; buildRowsFromEvents skips any stray encrypted event so it
can never surface in the public feed.
- state.visibility / state.privateDTag — restored on load, cleared on
Close project, autosaved.
Phase 2 — flip a published design's visibility in place:
- Owner-only Make Public / Make Private button on the preview page;
republishDesignVisibility re-publishes under the same d-tag with the
opposite wrapper (NIP-33 replace), behind a confirm that states the
public-to-private caveat.
Spec status documented in docs/PRIVATE_PUBLISHING_FEATURE.md.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Spec for publishing any design to Nostr encrypted, readable only by the
author (Phase 1 "private to me"). Covers the AES-256-GCM + NIP-44/NIP-04
key-wrap envelope, leak-free tagging (no casewrap feed tag, random d-tag),
progressive decryption in My Designs, an explicit threat model, and a
Phase 0 validation spike. Phases 2-4 (public/private toggle, recipients,
NIP-59/Blossom) sketched as future work.
Co-Authored-By: Claude Opus 4.7 <[email protected]>