Submissions are signed by throwaway ephemeral keys and public relays prune
events from pubkeys with no social graph, so the queue quietly evaporated.
- Forms: also publish to nos.lol (better retention, already in the app's
query set) alongside snort/damus/primal.
- submissionFacade: on each fetch, re-broadcast the still-pending signed
events back to our relays (publishEventToRelays) so pruning doesn't drop
them. Best-effort, fire-and-forget — never blocks or fails the fetch;
no-ops when no relay pool is available.
- test: fetch still returns the pending queue when a pool is present.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The forms hardcoded the maintainer's PUBLIC contact npub (npub13yarr7j… — the
blog/tip-jar/nostr persona, the old DM recipient) as the submission recipient,
but the admin Submissions tab queries submissions tagged to ADMIN_SUPER_NPUB
(npub15jnttpym…). Mismatch → the tab found nothing. Point all 5 forms' recipient
at ADMIN_SUPER_NPUB so submissions reach the admin whose tab lists them.
Lint + build clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
All 5 iframe forms now publish a PUBLIC, structured bitvid submission (kind 30083)
from their ephemeral key instead of a NIP-04 encrypted kind-4 DM — so the admin
Submissions tab can list + approve/deny them.
- application → k=application (+ applicant = the required npub)
- bug-fix → k=bug, feedback → k=feedback, request → k=feature
(each includes applicant only when the optional npub is filled in)
- content-appeals → k=appeal (no npub field)
Each tags ['d', <id>], ['k', <type>], ['p', <admin hex>], ['t','bitvid-submission'],
['client','bitvid']; the form body goes in plaintext content. The post-publish
verification subscription now watches kind 30083. No encryption anywhere.
Lint + build clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The embed submission forms accepted any free-text identifier and published it,
so they were an easy spam vector. Add a shared, testable NIP-19 validator and
require a well-formed npub before a submission is sent.
- js/utils/validateNpub.js: validateNpubHex() decodes via nostr-tools nip19 and
returns the 64-char hex pubkey, or null for anything that isn't a real npub
(free text, wrong prefix, bad checksum, wrong NIP-19 entity). Also exposed as
window.validateNpubHex for the classic iframe form scripts.
- Application form (required npub): submit is blocked unless valid; the decoded
hex is written into the application body for canonical storage/matching.
- Feature-request / bug-fix / feedback (optional npub): stays optional, but a
non-empty value must be a valid npub or submit is blocked with an inline error.
- Tests: tests/validate-npub.test.mjs (real nostr-tools, no implementation mirror).
Co-Authored-By: Claude Opus 4.8 <[email protected]>