Skip to content

Release: develop -> main - #70

Merged
TaprootFreak merged 12 commits into
mainfrom
develop
Aug 30, 2026
Merged

Release: develop -> main#70
TaprootFreak merged 12 commits into
mainfrom
develop

Conversation

@github-actions

Copy link
Copy Markdown

Automatic Release PR

Commits: 1 new commit(s)

  • Review all changes
  • Verify CI passes
  • Merge when ready for production

TaprootFreakAI and others added 12 commits August 30, 2026 14:28
* 01a04a23 - Publish kind:0 picture, NIP-65, and kind:1 photo imeta

* 01a04a23 - Keep zapped photo notes on their original event id

* 01a04a23 - Filter photo resign to unpaid rows at the store

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* Persist forum invoice attempts and zap ingest decisions.

POST /messages/:id/invoice now writes every attempt (success and failure)
to message_invoice, including the BOLT11, description vs description_hash,
and whether the invoice is a NIP-57 hash invoice. kind:9735 ingest
records indexed and rejected outcomes in nostr_zap_ingest. Operators can
list both via DEBUG_TOKEN GET /debug/invoices and GET /debug/zap-ingests.

* Document invoice and zap-ingest methods on the in-memory store.

Handbook bullets for migrateMessageSchema and InMemoryMessageStore now
name message_invoice, nostr_zap_ingest, and the matching store methods.

* Format CONTRIBUTING and debug-payments with Prettier.

CI lint failed prettier --check on three files; this matches the repo style.

* Cover invoice persist and zap-ingest mapper edge cases.

Adds tests for null/array JSON mapping, sign_failed invoice rows, a
non-object signed zap request, and ingest errors without a string pubkey
so coverage meets the 100% gate.

* Document debug invoice and zap-ingest routes in SPEC.

Adds GET /debug/invoices and GET /debug/zap-ingests to the route table
and contracts, and names the new tables in the CONTRIBUTING schema tree.

* Reject non-uuid message ids on the invoice route.

POST /messages/:id/invoice now uses the same uuid check as photo fetch, so
Postgres is not asked to cast garbage into message_invoice.message_id.

* Persist zap ingest when the receipt pubkey is not a string.

Invoice tests with a non-integer sats body now use a uuid path so the
new invoice id check does not turn them into 404.

* Document invoice UUID check and persist in SPEC and handbook.

POST /messages/:id/invoice now states the UUID guard, best-effort
message_invoice rows, and the full result union on GET /debug/invoices.

* Retrigger CI.

GitHub did not start check-runs on the previous two commits.

* Format CONTRIBUTING after rebase onto NIP-65 develop.

* Forward photo-reset store methods in persist test stubs.

After the NIP-65 rebase, MessageStore includes listSignedMissingPhoto and
resetSignedEvent; the invoice/ingest test doubles now implement them.

* Cover remaining persist branches for the 100% coverage gate.

Ignores zod/cap and missing-key persist that sit behind existing v8
guards, records a null zap_request bind, and marks the catch-path
pubkey ternary as unreachable after the ingest guard.

* Exercise inspectBolt11 fields on a successful forum invoice.

The ok persist path records paymentHash and descriptionHash when the
BOLT11 inspects, covering the non-null optional-chaining branches.

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* Allow operator-provisioned accounts and passkey claim by view key

POST /debug/accounts creates name plus Wallet of Satoshi rows without a
passkey. Register begin accepts viewKey so the owner can bind a passkey
to that same account.

* Tighten provision uniqueness and cover debug POST in e2e

Unique Lightning Address and one passkey per account. Playwright hits
POST /debug/accounts and claim begin with an unknown view key.

* Format the provision and claim files with Prettier

CI lint failed on six files after the uniqueness follow-up.

* Reject duplicate Lightning Addresses on create, update, and /me

Memory adapter matches the unique index. Linking someone else's address
returns 409. Claim-loser provision still updates the name.

* Document Lightning Address uniqueness in handbook and TSDoc

POST /me/lightning-address 409, unique indexes, and in-memory refuse
now match the adapters.

* Cover claim, provision race, and address 409 branches

CI coverage missed claim Nostr/passkey races, POST provision 500/loser
name update, and silent updateAccount refuse on /me.

* Document POST /debug/accounts 500 and drop a reachable v8 ignore

The provision 500 path is operator-visible. Claim Nostr keygen failure
is covered by a unit test, so it must stay in coverage.

* Align SPEC.md with provision and claim, cover nameless claim

POST /debug/accounts, optional viewKey begin, and 409 on a taken
Lightning Address now match the implemented HTTP surface.

* Normalize provision rows and keep one passkey per account

Validate every name and Lightning Address before writing on
POST /debug/accounts. Adapters refuse a second credential for the
same account. Docs and tests cover the 400 path and uniqueness.

* Document that claim user.id is the provisioned account

Mint still uses a pending UUID; a view-key claim encodes the existing row.

* Format the DEBUG_TOKEN row after the develop rebase

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* 01a04a23 - Give Damus image URLs a .jpg/.png/.webp extension

* 01a04a23 - Document photo Content-Disposition and .jpeg alias

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
Over-cap POST /messages/:id/invoice now persists bad_body instead of
hiding behind a coverage ignore. Debug invoice and zap-ingest lists
return 503 when the store throws, matching the other debug routes.

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* 01a052b6 - Put #bitcoin and #21gifts in kind:1 content

Damus renders hashtags from note text, not from hidden t tags.
Append the same discovery tags to kind:1 content and re-sign unpaid
notes that still lack them. Forum message text is unchanged.

* 01a052b6 - Keep hashtags in worker tests that CI runs

Photo notes without bytes still get #bitcoin #21gifts in content.
Zap ingest fixtures must already include those tags so re-sign does
not replace the event id the receipt points at.

* 01a052b6 - Format kind:1 photo URL tests after rebase

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
)

* Add self-hosted Web Push with VAPID and an outbox worker

Store browser subscriptions on the account, enqueue forum and zap
notifications, and send them when VAPID is configured. Missing keys
keep the process booting; push HTTP returns 503.

* Reject malformed VAPID keys without failing boot

Missing keys already returned 503. Garbage keys used to throw inside
web-push during sender construction and would take down the process.
Validate decoded lengths and subject, and catch constructor throws.

* Fix unconfigured push-route tests that used a default VAPID key

Passing undefined into the helper still applied the configured default,
so POST returned 200 and DELETE 404 instead of 503.

* Pin VAPID off in Playwright and assert debug ping 401 without bearer

Default e2e boot already sets DEBUG_TOKEN, so an unauthenticated
debug-ping is 401. Blank VAPID env so host keys cannot leak into the
booted process.

* Keep HTTP push off when VAPID construct fails and return stored createdAt

Boot now passes an explicit empty public key so createApp cannot pick
VAPID back up from the environment after a sender throw. Subscription
upsert returns the persisted createdAt, including rebinds.

* Cover push enqueue failures and drop a dead worker branch

Forum and zap ingest now have tests for enqueue throws. The worker
tick marks sent or failed without an unreachable else. Document
upsert return values.

* Document forum push enqueue and format CONTRIBUTING after rebase

messagesRoutes handbook and TSDoc now mention optional pushStore.
Prettier the env table after merging develop.

* Cover remaining VAPID branches and skip overlapping worker ticks

Empty/invalid base64, non-numeric push status codes, and Date leases
are tested. The interval will not start a second tick until the first
has settled.

* Retrigger pull_request CI on the current head

* Format docs after rebasing onto develop

* Split Date vs null claimed_until mapping tests

The null-lease case must stay null. Map a Date lease in its own test
so v8 covers the instanceof Date branch.

* Cover Date vs string timestamps and env VAPID on createApp

Postgres mappers now see both Date and ISO string created_at.
createApp without vapidPublicKey still reads a valid env pair.

* Use a current session timestamp in the env VAPID createApp test

createdAt of 1 was expired and evicted, so the request returned 401.

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* Reject non-NIP-57 forum invoices before returning pr

POST /messages/:id/invoice now returns { pr, amountSats } only when the
minted BOLT11 description_hash matches the zap request. Plaintext LN
invoices are persisted as not_zap for debug and rejected with 400 so
the client never shows a QR that cannot produce a kind:9735 receipt.

* Document that isNip57Invoice is only used for the invoice gate

The ok persist path stores a literal true after the gate, so the
handbook Used-by line must not claim a second call.

* Cover not_zap when the minted BOLT11 cannot be inspected

The 100% branch gate failed on inspected?.paymentHash when inspectBolt11
returns null (malformed LNURL invoice). Persist still stores the pr.

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* Update only the account name on provision upsert

POST /debug/accounts no longer rewrites the whole account row when the
Lightning Address already exists. Postgres SET name is atomic so a
concurrent role or rules write is not lost.

* Harden the name-only provision update against stale reads

Look up and mutate the in-memory row without yielding. Fail the
provision request when the persisted name is not the requested one.

* Document the name-mismatch 500 on provision upsert

POST /debug/accounts already returns 500 when the stored name is not
the requested name. SPEC and handbook now say so.

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
* 01a052b6 - Do not reset pending notes to stamp Damus hashtags

Resetting every signed row every tick renewed the 60s sign lease, so
nothing reached a relay — including new forum posts. Only published
unpaid notes are re-signed, and only after unsigned rows are signed,
matching the photo-URL lease rule.

* 01a052b6 - Align photo and hashtag resign after sign

Both published-only resets now run after unsigned rows are signed, so
new forum posts are not queued behind a 20-row rewrite of old notes.
Pending notes still EVENT without being reset. Docs match that order.

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
noZap and not_zap now 400 with a stable English string so the app can
tell the payer the author's wallet cannot receive the payment, without
showing a QR. Unreachable LNURL still uses the generic start-payment error.

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
@TaprootFreak
TaprootFreak merged commit e12019c into main Aug 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants