Skip to content

feat: add http-nostr knowledge#33

Open
Dunsin-cyber wants to merge 2 commits intogetAlby:masterfrom
Dunsin-cyber:feat/add-http-nostr
Open

feat: add http-nostr knowledge#33
Dunsin-cyber wants to merge 2 commits intogetAlby:masterfrom
Dunsin-cyber:feat/add-http-nostr

Conversation

@Dunsin-cyber
Copy link
Contributor

@Dunsin-cyber Dunsin-cyber commented Feb 20, 2026

fixes #11 and #27

What?

This PR integrates knowledge of the HTTP-Nostr bridge into the Alby Bitcoin Payments Agent Skill, teaching the agent how to build robust, serverless NIP-47 applications.

Why?

Because persistent WebSockets (client.subscribeNotifications) fail and timeout in serverless environments (like Vercel or AWS Lambda), developers need an alternative to receive payment notifications. The HTTP-Nostr bridge solves this by converting Nostr events into HTTP Webhooks.

Summary by CodeRabbit

  • New Features

    • Added an HTTP‑Nostr Serverless Bridge enabling publish/subscribe/delete flows for Nostr events via HTTP webhooks.
    • Added wallet-related actions to interact with NIP‑47 Lightning wallets (sync/async requests, notifications, push subscriptions).
  • Documentation

    • Comprehensive HTTP‑Nostr docs with deployment options (hosted or self‑hosted) and environment guidance (persistent WebSocket vs serverless HTTP).
    • New guides on event subscriptions, publishing, and subscription cleanup.

@coderabbitai
Copy link

coderabbitai bot commented Feb 20, 2026

Warning

Rate limit exceeded

@Dunsin-cyber has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 53 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

This PR adds HTTP-Nostr documentation and TypeScript typings for a serverless bridge that exposes Nostr/NIP-47 operations over HTTP webhooks, plus guidance on deployment options and environment constraints for persistent vs serverless setups.

Changes

Cohort / File(s) Summary
Skill doc
SKILL.md
Added HTTP-Nostr entry to skill references and an Environment Constraints section distinguishing Persistent (WebSocket) and Serverless (HTTP-Nostr Webhook) deployments; minor presentation tweak to wallet reference.
HTTP‑Nostr overview & deployment
references/http-nostr/http-nostr.md
New doc describing the HTTP‑Nostr Serverless Bridge, two deployment options (Alby Hosted API, Self‑Hosted), base URLs, setup steps, and links to typings and NIP‑47 guidance.
API: general events & subscriptions
references/http-nostr/general-nostr-events.md
New API documentation for POST /publish, POST /subscriptions, and DELETE /subscriptions/:id covering publish, webhook-based subscriptions, and subscription cleanup semantics and errors.
NIP-47 wallet actions
references/http-nostr/nip47-wallet-actions.md
New doc describing wallet-related endpoints: capability checks, synchronous/asynchronous NIP‑47 requests, webhook notifications, and push subscription flows.
TypeScript typings
references/http-nostr/index.d.ts
Added interfaces for NostrEvent, NostrFilter, error/Info/NIP‑47/Publish/Subscription request & response types and related payload contracts (multiple new exported interfaces).

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client (app)
  participant Bridge as HTTP‑Nostr Bridge\n(serverless)
  participant Relay as Nostr Relay
  participant DB as PostgreSQL
  participant Webhook as Client Webhook\n(receiver)

  Client->>Bridge: POST /subscriptions {filter, webhook_url}
  Bridge->>DB: store subscription
  Bridge->>Relay: subscribe with filter
  Relay-->>Bridge: matching events
  Bridge->>Webhook: POST /webhook (event)
  Note over Bridge,DB: DELETE /subscriptions/:id stops Relay subscription and removes DB record
Loading
sequenceDiagram
  participant Client as Client (app)
  participant Bridge as HTTP‑Nostr Bridge
  participant Relay as Nostr Relay

  Client->>Bridge: POST /publish {signed_event}
  Bridge->>Relay: publish event
  Relay-->>Bridge: ACK / error
  Bridge->>Client: 200 OK / ErrorResponse
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through types and webhook trails,
I stitched NIP‑47 into airy veils,
Events take flight from bridge to ear,
Wallets whisper, webhooks cheer,
A tiny rabbit applauds this patch with twinkling tails ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add http-nostr knowledge' is specific and directly relates to the main changes, which introduce HTTP-Nostr documentation and TypeScript typings to the skill knowledge base.
Linked Issues check ✅ Passed The PR addresses the primary objective of issue #11 by adding comprehensive HTTP-Nostr knowledge including documentation, TypeScript interfaces, and references for serverless NIP-47 applications.
Out of Scope Changes check ✅ Passed All changes are within scope: SKILL.md updates reference the new HTTP-Nostr content, and all new files (http-nostr documentation and index.d.ts typings) directly support the HTTP-Nostr knowledge objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
references/http-nostr/general-nostr-events.md (1)

8-8: Minor wording: "outside of" is redundant

outside of NIP-47 specific requestsoutside NIP-47 specific requests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@references/http-nostr/general-nostr-events.md` at line 8, Change the wording
in the sentence that reads "Publishes any signed Nostr event (outside of NIP-47
specific requests) to a specified relay." to remove the redundant "of" so it
reads "Publishes any signed Nostr event (outside NIP-47 specific requests) to a
specified relay."; update the parenthetical phrase only and keep the rest of the
sentence unchanged.
references/http-nostr/index.d.ts (2)

94-104: Inconsistent casing between SubscriptionResponse and PushSubscriptionResponse

SubscriptionResponse.subscription_id uses snake_case while PushSubscriptionResponse.subscriptionId uses camelCase. This is likely inherited from different serialization tags in the Go source, but it's a sharp edge for TypeScript consumers who will expect consistent property naming across related response types. Consider documenting the discrepancy with an inline comment, or align casing if the wire format permits.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@references/http-nostr/index.d.ts` around lines 94 - 104, SubscriptionResponse
uses snake_case for subscription_id while PushSubscriptionResponse uses
camelCase for subscriptionId; update the types to be consistent by either
renaming SubscriptionResponse.subscription_id -> subscriptionId (and add a
comment about mapping to the wire format if needed) or rename
PushSubscriptionResponse.subscriptionId -> subscription_id to match the wire
format, and add an inline comment on both interfaces (SubscriptionResponse and
PushSubscriptionResponse) explaining the choice and any serialization mapping to
avoid confusion for TypeScript consumers.

74-75: state fields typed as string — consider string literal unions

NIP47Response.state, PublishResponse.state (Line 85), and StopSubscriptionResponse.state (Line 108) all have their valid values documented only in inline comments. Narrowing to string literal union types provides exhaustiveness checking, IntelliSense autocomplete, and prevents typos at call sites.

♻️ Proposed narrowing for state fields
 export interface NIP47Response {
   event?: NostrEvent;
-  state: string; // "PUBLISHED", "ALREADY_PROCESSED", "WEBHOOK_RECEIVED"
+  state: "PUBLISHED" | "ALREADY_PROCESSED" | "WEBHOOK_RECEIVED";
 }

 export interface PublishResponse {
   eventId: string;
   relayUrl: string;
-  state: string;
+  state: "PUBLISHED" | "ALREADY_PROCESSED";
 }

 export interface StopSubscriptionResponse {
   message: string;
-  state: string; // "CLOSED", "ALREADY_CLOSED"
+  state: "CLOSED" | "ALREADY_CLOSED";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@references/http-nostr/index.d.ts` around lines 74 - 75, The three response
types currently declare state as a plain string; update NIP47Response.state,
PublishResponse.state, and StopSubscriptionResponse.state to use string literal
union types listing their documented values (e.g., "PUBLISHED" |
"ALREADY_PROCESSED" | "WEBHOOK_RECEIVED" or the specific valid tokens for each
response) so callers get exhaustiveness checking and autocompletion; locate the
interfaces by name in index.d.ts and replace the string-typed state properties
with the appropriate union of literal strings for each interface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@references/http-nostr/http-nostr.md`:
- Around line 33-34: The two markdown links in the API Reference ("NIP-47 Wallet
Actions" and "General Nostr Events") include a redundant "http-nostr/" path
segment; edit the links in http-nostr.md so they point to the sibling documents
(remove the extra "http-nostr/" from each link target) so the references resolve
correctly.

In `@SKILL.md`:
- Line 27: The markdown link "(./references/http-nostr.md)" in SKILL.md under
the "Serverless (Vercel/Lambda): WebSockets are NOT supported." line points to a
non-existent file—update that link target to the actual http-nostr markdown
located in the references/http-nostr directory (replace the broken
"(./references/http-nostr.md)" link with the correct nested path to
http-nostr.md) and verify the link resolves in the rendered docs.

---

Nitpick comments:
In `@references/http-nostr/general-nostr-events.md`:
- Line 8: Change the wording in the sentence that reads "Publishes any signed
Nostr event (outside of NIP-47 specific requests) to a specified relay." to
remove the redundant "of" so it reads "Publishes any signed Nostr event (outside
NIP-47 specific requests) to a specified relay."; update the parenthetical
phrase only and keep the rest of the sentence unchanged.

In `@references/http-nostr/index.d.ts`:
- Around line 94-104: SubscriptionResponse uses snake_case for subscription_id
while PushSubscriptionResponse uses camelCase for subscriptionId; update the
types to be consistent by either renaming SubscriptionResponse.subscription_id
-> subscriptionId (and add a comment about mapping to the wire format if needed)
or rename PushSubscriptionResponse.subscriptionId -> subscription_id to match
the wire format, and add an inline comment on both interfaces
(SubscriptionResponse and PushSubscriptionResponse) explaining the choice and
any serialization mapping to avoid confusion for TypeScript consumers.
- Around line 74-75: The three response types currently declare state as a plain
string; update NIP47Response.state, PublishResponse.state, and
StopSubscriptionResponse.state to use string literal union types listing their
documented values (e.g., "PUBLISHED" | "ALREADY_PROCESSED" | "WEBHOOK_RECEIVED"
or the specific valid tokens for each response) so callers get exhaustiveness
checking and autocompletion; locate the interfaces by name in index.d.ts and
replace the string-typed state properties with the appropriate union of literal
strings for each interface.

@rolznz
Copy link
Collaborator

rolznz commented Feb 20, 2026

Hi @Dunsin-cyber thanks for the PR. We are currently undecided if this is actually a good way to go because it creates competing ways of doing things, which makes more confusion for developers and agents.

I will keep this PR open for now and think about it. CC @bumi

@Dunsin-cyber
Copy link
Contributor Author

Hi @Dunsin-cyber thanks for the PR. We are currently undecided if this is actually a good way to go because it creates competing ways of doing things, which makes more confusion for developers and agents.

I will keep this PR open for now and think about it. CC @bumi

alright, noted.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@SKILL.md`:
- Line 55: Add a terminal period to the sentence "If they do not have a wallet
yet [here are some options](./references/production-wallets.md)" in SKILL.md so
it ends with a period; locate that exact sentence text and append a period to
complete the sentence.

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.

Add knowledge of http-nostr

2 participants