Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -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 GitHub Copilot produce code that respects the repository's conventions and protocol requirements.
28 changes: 28 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -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}}
Comment thread
tcheeric marked this conversation as resolved.

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"
17 changes: 17 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## Summary
<!-- What motivated this change? -->

## What changed?
<!-- Provide a concise summary of the changes. -->

## Breaking changes
- [ ] BREAKING: this change introduces breaking API or behavior

## Review focus
<!-- Highlight areas that need the most attention from reviewers. -->

## Checklist
- [ ] Tests added or updated
- [ ] `mvn -q verify` passes
- [ ] Documentation updated (README, docs, etc.)
- [ ] No unused imports
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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: mvn -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'

29 changes: 29 additions & 0 deletions .github/workflows/enforce_conventional_commits.yml
Original file line number Diff line number Diff line change
@@ -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 }}
26 changes: 26 additions & 0 deletions .github/workflows/google-java-format.yml
Original file line number Diff line number Diff line change
@@ -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@v5
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 }}
28 changes: 28 additions & 0 deletions .github/workflows/qodana.yml
Original file line number Diff line number Diff line change
@@ -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
Comment thread
tcheeric marked this conversation as resolved.
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'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ logs/
*.swp
*.swo
*~
/.claude/
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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]

### 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

- Enforce auth requirement for REQ messages when `require-auth=true`

## [0.1.0] - 2026-01-06
Comment thread
tcheeric marked this conversation as resolved.

### 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
17 changes: 15 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.5</version>
<version>3.5.8</version>
<relativePath/>
</parent>

<groupId>xyz.tcheeric</groupId>
<artifactId>nostr-auth-proxy</artifactId>
<version>0.1.0</version>
<version>0.1.1</version>
<packaging>jar</packaging>

<name>Nostr Auth Proxy</name>
Expand All @@ -26,8 +26,21 @@
<bcprov-jdk18on.version>1.81</bcprov-jdk18on.version>
<testcontainers.version>1.20.4</testcontainers.version>
<awaitility.version>4.3.0</awaitility.version>
<!-- Override transitive dependency versions for CVE fixes -->
<commons-lang3.version>3.18.0</commons-lang3.version>
</properties>

<dependencyManagement>
<dependencies>
<!-- CVE-2024-25710, CVE-2024-26308: fix in 1.26.0+ -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.27.1</version>
</dependency>
</dependencies>
</dependencyManagement>

<distributionManagement>
<repository>
<id>reposilite-releases</id>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Loading