diff --git a/AGENTS.md b/AGENTS.md index 01f207c..a593df0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1758,6 +1758,55 @@ session with **no other memory of this project**. So: out: `git add -A` in the repo root sweeps these in. - **Never `git add -A` from the repo root** without checking `git status` first. +## Angor crowdfunding — the SkateSpots project (2026-10-05) + +SkateSpots is crowdfunded on **Angor** (Bitcoin + Nostr, no middleman). This is +*separate* from the app code: a live on-chain project whose metadata is ordinary +Nostr events signed by a **project identity** (derived from the founder's wallet, +**not** the personal npub). + +- **projectIdentifier** (the kind-3030 `d`): `angor1qtunna00uqyx52rr0nvqa059z2gknhrmn7urd6z` + → Bitcoin address `bc1qtunna00uqyx52rr0nvqa059z2gknhrmnqe7h8h`. +- **project Nostr key** (signs profile + metadata): `a99eb1d4d546d3a3b40040cc93f77b9a7cd32fab1b693261e03ff1b7ce7400f` + = `npub14x0tr4rd23kn5w6qqsxvj0mhhxnu6vh6kxmfxfs7q0l3kl88gq8sfgwk54`. + ⚠️ **Different from the personal/platform key** `20e7c953…` (`npub1yrnuj…`, the git origin). +- **kind 3030** = funding definition (Fund type, Main, penalty 90d, threshold 100k sats, + 3/6/9-monthly stage patterns). Its event id is committed **on-chain via OP_RETURN** → + **effectively immutable; do not edit**. +- **Editable metadata** = **kind 0** profile + **kind 30078** (`angor:project`, `angor:faq`, + `angor:members`, `angor:media`). Live: displayName "Skate Spots", NIP-05 + `owner@skate-spots.org`, lud16 `skatespots@minibits.cash` (single-sourced in + `src/lib/platform.ts`), picture on `blossom.angor.io`. + +### Tooling — machine-local, deliberately NOT in the repo +`~/.config/skatespots/angor/` → `angor-metadata.mjs` + `blossom-upload.mjs` (own +`nostr-tools`/`ws`). The project nsec lives in `~/.config/skatespots/angor/key` (mode 600, +outside the repo); the tool **refuses** any key whose pubkey ≠ the project key. +`check` · `dump`/`show` · `publish [--yes] [--only …]` · `emit` · `claim-nip05 ` · +`blossom-upload.mjs `. Get the nsec from the app: project → **Private keys** +(the modal is titled **"Project NOSTR Private Keys"**; feet at `m/44'/1237'/{upi}'/0/0`). + +### ⚠️ Gotchas that cost a whole session +- **Publish to ALL SIX relays the app uses**: `relay.angor.io`, `relay2.angor.io`, + `relay.damus.io`, `nos.lol`, `nostr-01.yakihonne.com`, `nostr-02.yakihonne.com`. + `RelayService.FetchProfileMetadataAsync` does `result = metadata` on every reply — + **last response wins, not the newest event** — so one relay still holding an older kind 0 + overrides the update. (The project originally lived only on YakiHonne.) +- **The app's Edit Profile "Save Profile" republishes whatever the form shows.** While the + NIP-05/Lightning fields are blank, saving **wipes** them. Don't save until they load. +- **The app's Relays tab is cosmetic** — `EditProfileViewModel.SaveAsync` never persists + `Relays` and `LoadAsync` never loads them; adding relays there does nothing. +- **`nostr-tools` SimplePool + Node's built-in WebSocket is broken here**: it reports a fake + `✔` with no relay `OK`, and overflows the stack on a failed connect. The tool talks raw + `ws` and waits for the relay's real `OK` — trust that output, not the old pool behaviour. +- **NIP-05:** `skate-spots@skate-spots.org` is already bound to the personal key; a project + profile needs a name that maps to the **project** key. `claim-nip05 owner` → + `owner@skate-spots.org` (registry = `netlify/functions/nip05.mjs`, proof-by-signature). +- Blossom (blossom.angor.io) returns a **doubled-scheme URL** (`https://https://…`); build + `/.` yourself and verify the sha256 on download. + +`nak` is installed (`~/.local/bin/nak`) — handy for `nak req` / `nak event` against these relays. + ## Local Dev Environment, Build & Release (project-specific — read first) Machine-specific, verified operational notes. Use these instead of re-deriving workflows from scratch.