From f6fadaedd80f124aaba4bcee1def693830eab1ca Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 6 Jan 2026 19:12:05 +0000 Subject: [PATCH 1/8] docs: rewrite copilot instructions for nostr-auth-proxy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace Cashu/NUT references with relevant Nostr NIPs (NIP-01, NIP-42, and protected kinds). Add architecture diagram and key components section. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .github/copilot-instructions.md | 40 +++++++++ .github/dependabot.yml | 28 +++++++ .github/pull_request_template.md | 17 ++++ .github/workflows/ci.yml | 83 +++++++++++++++++++ .../enforce_conventional_commits.yml | 29 +++++++ .github/workflows/google-java-format.yml | 26 ++++++ .github/workflows/qodana.yml | 28 +++++++ 7 files changed, 251 insertions(+) create mode 100644 .github/copilot-instructions.md create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/enforce_conventional_commits.yml create mode 100644 .github/workflows/google-java-format.yml create mode 100644 .github/workflows/qodana.yml diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..1e427fb --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,40 @@ +# GitHub Copilot Instructions + +This repository implements a NIP-42 authentication proxy for Nostr relays. It adds client authentication support to upstream relays (like strfry) that don't natively support it. + +## Guidelines + +- Use Conventional Commits for titles and commit messages (e.g., `feat(scope): message`). +- Ensure pull requests include a clear description and test results. +- Reference related issues using `Closes #123` when applicable. +- Run `mvn -q verify` before committing code. +- Document new features in the README or related docs. +- Maintain Java 21 compatibility and update `pom.xml` for new dependencies. +- Remove unused imports. + +## Relevant Nostr NIPs + +When implementing features, consult the relevant NIP specifications: + +- [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) - Basic protocol flow (events, subscriptions, messages) +- [NIP-42](https://github.com/nostr-protocol/nips/blob/master/42.md) - Client authentication (core to this proxy) +- [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md) - Encrypted direct messages (protected kind) +- [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) - Private direct messages (protected kinds 14, 15) +- [NIP-46](https://github.com/nostr-protocol/nips/blob/master/46.md) - Nostr Connect / remote signing (protected kind 24133) +- [NIP-47](https://github.com/nostr-protocol/nips/blob/master/47.md) - Wallet Connect (protected kinds 23194-23197) +- [NIP-59](https://github.com/nostr-protocol/nips/blob/master/59.md) - Gift wraps (protected kinds 13, 1059) + +## Architecture + +``` +Client (port 7777) ←→ NIP-42 Auth Proxy ←→ Upstream Relay (strfry @ 7778) +``` + +Key components: +- `auth/` - NIP-42 authentication and BIP-340 signature verification +- `session/` - WebSocket session management and state tracking +- `access/` - Access control (open, allowlist, blocklist modes) +- `handler/` - WebSocket message handling and upstream routing +- `upstream/` - Upstream relay client connections + +These instructions help Copilot produce code that respects the repository's conventions and protocol requirements. \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5de893e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,28 @@ +version: 2 + +# Private registries used by Dependabot +registries: + maven-releases: + type: maven-repository + url: https://maven.398ja.xyz/releases + username: ${{secrets.MVN_USER}} + password: ${{secrets.MVN_PASSWORD}} + maven-snapshots: + type: maven-repository + url: https://maven.398ja.xyz/snapshots + username: ${{secrets.MVN_USER}} + password: ${{secrets.MVN_PASSWORD}} + +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + target-branch: "develop" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + target-branch: "develop" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..2fb9275 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +## Summary + + +## What changed? + + +## Breaking changes +- [ ] BREAKING: this change introduces breaking API or behavior + +## Review focus + + +## Checklist +- [ ] Tests added or updated +- [ ] `mvn -q verify` passes +- [ ] Documentation updated (README, docs, etc.) +- [ ] No unused imports \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ba58cd3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,83 @@ +name: CI + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + cache: 'maven' + - name: Build with Maven + run: ./mvnw -q verify + - name: Upload surefire reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: surefire-reports + path: '**/target/surefire-reports' + if-no-files-found: ignore + - name: Upload JaCoCo coverage + if: always() + uses: actions/upload-artifact@v4 + with: + name: jacoco-exec + path: '**/target/jacoco.exec' + if-no-files-found: ignore + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + files: '**/target/site/jacoco/jacoco.xml' + token: ${{ secrets.CODECOV_TOKEN }} + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: '**/target/surefire-reports/*.xml' + + # E2E tests run with both autopay modes to verify payment flows + e2e-tests: + runs-on: ubuntu-latest + needs: build + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + strategy: + fail-fast: false + matrix: + autopay: [true, false] + env: + PHOENIXD_AUTOPAY_ENABLED: ${{ matrix.autopay }} + PHOENIXD_AUTO_SETTLE_DELAY_SECONDS: 1 + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + cache: 'maven' + - name: Build gateway-app + run: ./mvnw package -pl gateway-plugin/gateway-app -am -DskipTests -q + - name: Start infrastructure + run: | + docker compose -f docker-compose.gateway-e2e.yml up -d --build + sleep 30 + - name: Run E2E Tests (autopay=${{ matrix.autopay }}) + run: ./mvnw verify -Pe2e-gateway -pl gateway-plugin/gateway-e2e -Dtest.autopay=${{ matrix.autopay }} + - name: Stop infrastructure + if: always() + run: docker compose -f docker-compose.gateway-e2e.yml down -v + - name: Upload E2E test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-reports-autopay-${{ matrix.autopay }} + path: '**/target/allure-results' + if-no-files-found: ignore diff --git a/.github/workflows/enforce_conventional_commits.yml b/.github/workflows/enforce_conventional_commits.yml new file mode 100644 index 0000000..89dc3bd --- /dev/null +++ b/.github/workflows/enforce_conventional_commits.yml @@ -0,0 +1,29 @@ +name: Conventional Commits + +permissions: + contents: read + pull-requests: read + +on: + pull_request: + branches: + - main + - develop + +jobs: + commit-lint: + name: Verify Conventional Commits + if: (github.event_name == 'pull_request' && !startsWith(github.event.pull_request.head.ref, 'release-please--')) + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Check Commit Messages + uses: wagoid/commitlint-github-action@v6 + with: + configFile: .commitlintrc.yml + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/google-java-format.yml b/.github/workflows/google-java-format.yml new file mode 100644 index 0000000..e894fc0 --- /dev/null +++ b/.github/workflows/google-java-format.yml @@ -0,0 +1,26 @@ +name: Format + +on: + pull_request: + branches: + - main + +permissions: + contents: write + +jobs: + + formatting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 # v2 minimum required + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + - uses: axel-op/googlejavaformat-action@v4 + with: + args: "--replace" + # Recommended if you use MacOS: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/qodana.yml b/.github/workflows/qodana.yml new file mode 100644 index 0000000..82fee59 --- /dev/null +++ b/.github/workflows/qodana.yml @@ -0,0 +1,28 @@ +name: Qodana +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + - develop + +jobs: + qodana: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + checks: write + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit + fetch-depth: 0 # a full history is required for pull request analysis + - name: 'Qodana Scan' + uses: JetBrains/qodana-action@v2025.2 + with: + pr-mode: false + env: + QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} + QODANA_ENDPOINT: 'https://qodana.cloud' \ No newline at end of file From d81b3a00765b849b589b514eb42c67d06cd9114b Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 6 Jan 2026 19:19:57 +0000 Subject: [PATCH 2/8] chore(release): bump version to 0.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Projects updated: - nostr-auth-proxy: 0.1.0 → 0.1.1 (patch) Changes include: - Fixed auth requirement enforcement for REQ messages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .gitignore | 1 + CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ pom.xml | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/.gitignore b/.gitignore index 95a79dc..d5781da 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ logs/ *.swp *.swo *~ +/.claude/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2c4f8ab --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,31 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.1] - 2026-01-06 + +### Fixed + +- Enforce auth requirement for REQ messages when `require-auth=true` + +## [0.1.0] - 2026-01-06 + +### Added + +- Initial standalone nostr-auth-proxy project +- NIP-42 client authentication with BIP-340 signature verification +- WebSocket proxy to upstream Nostr relays (strfry) +- Session management with per-pubkey connection limits +- Access control modes: open, allowlist, blocklist +- Protection for privacy-sensitive event kinds (DMs, wallet data, etc.) +- Spring Boot Actuator health checks and Prometheus metrics +- Docker image support via Jib + +[Unreleased]: https://github.com/tcheeric/nostr-auth-proxy/compare/v0.1.1...HEAD +[0.1.1]: https://github.com/tcheeric/nostr-auth-proxy/compare/v0.1.0...v0.1.1 +[0.1.0]: https://github.com/tcheeric/nostr-auth-proxy/releases/tag/v0.1.0 diff --git a/pom.xml b/pom.xml index 2461547..f3df801 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ xyz.tcheeric nostr-auth-proxy - 0.1.0 + 0.1.1 jar Nostr Auth Proxy From 1be6a032847455114455fe787aff90de0e318603 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 6 Jan 2026 20:42:03 +0000 Subject: [PATCH 3/8] fix(ci): use system Maven instead of wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mvnw wrapper script was not present in the repository. Also removed e2e-tests job that referenced non-existent paths from a different project. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba58cd3..dad8912 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: distribution: 'temurin' cache: 'maven' - name: Build with Maven - run: ./mvnw -q verify + run: mvn -q verify - name: Upload surefire reports if: always() uses: actions/upload-artifact@v4 @@ -44,40 +44,3 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} files: '**/target/surefire-reports/*.xml' - # E2E tests run with both autopay modes to verify payment flows - e2e-tests: - runs-on: ubuntu-latest - needs: build - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - strategy: - fail-fast: false - matrix: - autopay: [true, false] - env: - PHOENIXD_AUTOPAY_ENABLED: ${{ matrix.autopay }} - PHOENIXD_AUTO_SETTLE_DELAY_SECONDS: 1 - steps: - - uses: actions/checkout@v5 - - uses: actions/setup-java@v5 - with: - java-version: '21' - distribution: 'temurin' - cache: 'maven' - - name: Build gateway-app - run: ./mvnw package -pl gateway-plugin/gateway-app -am -DskipTests -q - - name: Start infrastructure - run: | - docker compose -f docker-compose.gateway-e2e.yml up -d --build - sleep 30 - - name: Run E2E Tests (autopay=${{ matrix.autopay }}) - run: ./mvnw verify -Pe2e-gateway -pl gateway-plugin/gateway-e2e -Dtest.autopay=${{ matrix.autopay }} - - name: Stop infrastructure - if: always() - run: docker compose -f docker-compose.gateway-e2e.yml down -v - - name: Upload E2E test reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: e2e-reports-autopay-${{ matrix.autopay }} - path: '**/target/allure-results' - if-no-files-found: ignore From a7c1fa3d5baf1e67e6112c3d6d932fc1a41ea470 Mon Sep 17 00:00:00 2001 From: Eric T Date: Tue, 6 Jan 2026 20:48:44 +0000 Subject: [PATCH 4/8] chores(documentation): Update .github/copilot-instructions.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1e427fb..0f4376d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -37,4 +37,4 @@ Key components: - `handler/` - WebSocket message handling and upstream routing - `upstream/` - Upstream relay client connections -These instructions help Copilot produce code that respects the repository's conventions and protocol requirements. \ No newline at end of file +These instructions help GitHub Copilot produce code that respects the repository's conventions and protocol requirements. \ No newline at end of file From aeb8126ef68dbcce2afc60b08a86b9c4c7a2268b Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 6 Jan 2026 20:50:12 +0000 Subject: [PATCH 5/8] fix: add null checks for upstream response body MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes Qodana DataFlowIssue warnings: - Nip11HandshakeInterceptor: handle null body from upstream - Nip11FilterConfig: handle null body from upstream 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../xyz/tcheeric/nostr/authproxy/filter/Nip11FilterConfig.java | 3 ++- .../nostr/authproxy/handler/Nip11HandshakeInterceptor.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/xyz/tcheeric/nostr/authproxy/filter/Nip11FilterConfig.java b/src/main/java/xyz/tcheeric/nostr/authproxy/filter/Nip11FilterConfig.java index 66c61c2..12cb6b4 100644 --- a/src/main/java/xyz/tcheeric/nostr/authproxy/filter/Nip11FilterConfig.java +++ b/src/main/java/xyz/tcheeric/nostr/authproxy/filter/Nip11FilterConfig.java @@ -111,9 +111,10 @@ private void handleNip11Request(HttpServletResponse response) throws IOException request, String.class); + String body = upstreamResponse.getBody(); response.setContentType("application/nostr+json"); response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().write(upstreamResponse.getBody()); + response.getWriter().write(body != null ? body : "{}"); response.getWriter().flush(); log.info("nip11_response_sent"); diff --git a/src/main/java/xyz/tcheeric/nostr/authproxy/handler/Nip11HandshakeInterceptor.java b/src/main/java/xyz/tcheeric/nostr/authproxy/handler/Nip11HandshakeInterceptor.java index 4363622..9ac1e33 100644 --- a/src/main/java/xyz/tcheeric/nostr/authproxy/handler/Nip11HandshakeInterceptor.java +++ b/src/main/java/xyz/tcheeric/nostr/authproxy/handler/Nip11HandshakeInterceptor.java @@ -83,8 +83,9 @@ private void handleNip11Request(ServerHttpResponse response) throws IOException request, String.class); + String body = upstreamResponse.getBody(); response.getHeaders().set("Content-Type", "application/nostr+json"); - response.getBody().write(upstreamResponse.getBody().getBytes()); + response.getBody().write(body != null ? body.getBytes() : "{}".getBytes()); response.getBody().flush(); log.info("nip11_response_sent"); From 868e78d6028723c3cc767b101d0a6ab32ff6d466 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 6 Jan 2026 20:50:59 +0000 Subject: [PATCH 6/8] chore(ci): update setup-java to v5 for consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .github/workflows/google-java-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/google-java-format.yml b/.github/workflows/google-java-format.yml index e894fc0..536a472 100644 --- a/.github/workflows/google-java-format.yml +++ b/.github/workflows/google-java-format.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v5 # v2 minimum required - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' From d6a1e0624598960e1b7e18e27c69d51de9db740e Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 6 Jan 2026 20:57:03 +0000 Subject: [PATCH 7/8] fix(deps): upgrade dependencies to address CVEs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Spring Boot 3.5.5 → 3.5.8 - Fixes CVE-2025-41249 (spring-core 6.2.14) - Fixes CVE-2025-41254 (spring-websocket 6.2.14) - Fixes CVE-2025-55754 (tomcat-embed-core 10.1.49) - Fixes CVE-2025-11226 (logback-core 1.5.21) - commons-lang3 3.17.0 → 3.18.0 - Fixes CVE-2025-48924 - commons-compress 1.24.0 → 1.27.1 - Fixes CVE-2024-25710, CVE-2024-26308 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- pom.xml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f3df801..f817011 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.5 + 3.5.8 @@ -26,8 +26,21 @@ 1.81 1.20.4 4.3.0 + + 3.18.0 + + + + + org.apache.commons + commons-compress + 1.27.1 + + + + reposilite-releases From a2a41ba1c36981edcda77218dc298641acc461c8 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 6 Jan 2026 20:58:31 +0000 Subject: [PATCH 8/8] docs: update CHANGELOG with recent fixes and security updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c4f8ab..b5fb607 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Add null checks for upstream response body in NIP-11 handlers +- Use system Maven instead of wrapper in CI workflow + +### Changed + +- Update `actions/setup-java` to v5 in google-java-format workflow + +### Security + +- Upgrade Spring Boot 3.5.5 → 3.5.8 (fixes CVE-2025-41249, CVE-2025-41254, CVE-2025-55754, CVE-2025-11226) +- Upgrade commons-lang3 3.17.0 → 3.18.0 (fixes CVE-2025-48924) +- Upgrade commons-compress 1.24.0 → 1.27.1 (fixes CVE-2024-25710, CVE-2024-26308) + ## [0.1.1] - 2026-01-06 ### Fixed