Skip to content

Commit 0b01d87

Browse files
authored
Merge pull request #502 from tcheeric/develop
Release v1.2.1
2 parents f14cf03 + abb5ec9 commit 0b01d87

25 files changed

Lines changed: 582 additions & 123 deletions

File tree

.github/pull_request_template.md

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,45 @@
11
## Summary
2-
<!-- Explain the problem, context, and why this change is needed. Link to the issue. -->
32

4-
Related issue: #____
3+
<!-- Briefly explain the problem and why this change is needed. -->
4+
5+
Closes #____
6+
7+
## Type of change
8+
9+
<!-- Check all that apply -->
10+
11+
- [ ] `fix` - Bug fix (non-breaking)
12+
- [ ] `feat` - New feature (non-breaking)
13+
- [ ] `refactor` - Code change that neither fixes a bug nor adds a feature
14+
- [ ] `docs` - Documentation only
15+
- [ ] `test` - Adding or updating tests
16+
- [ ] `perf` - Performance improvement
17+
- [ ] `chore` - Build, CI, or tooling changes
518

619
## What changed?
7-
<!-- Brief summary; suggest where to start reviewing if many files. -->
820

9-
## BREAKING
10-
<!-- If applicable, call it out explicitly. -->
11-
<!-- ⚠️ BREAKING: Describe migration or impact. -->
21+
<!-- Brief summary of changes. For large PRs, suggest where to start reviewing. -->
22+
23+
## Breaking changes
24+
25+
<!-- Delete this section if not applicable -->
26+
<!-- ⚠️ BREAKING: Describe migration steps or impact on existing code. -->
27+
28+
## Testing
29+
30+
<!-- How was this tested? Include commands, test classes, or manual verification steps. -->
31+
32+
- [ ] Unit tests pass: `mvn test`
33+
- [ ] Integration tests pass: `mvn verify` (requires Docker)
1234

1335
## Review focus
14-
<!-- Ask for specific feedback, e.g., "Concurrency strategy OK?" or "API shape acceptable?" -->
36+
37+
<!-- Optional: Ask for specific feedback, e.g., "Is the error handling approach OK?" -->
1538

1639
## Checklist
17-
- [ ] Scope ≤ 300 lines (or split/stack)
18-
- [ ] Title is **verb + object** (e.g., “Refactor auth middleware to async”)
19-
- [ ] Description links the issue and answers “why now?”
20-
- [ ] **BREAKING** flagged if needed
21-
- [ ] Tests/docs updated (if relevant)
40+
41+
- [ ] PR title follows conventional commits: `type(scope): description`
42+
- [ ] Changes are focused and under 300 lines (or stacked PRs)
43+
- [ ] Tests added/updated for new functionality
44+
- [ ] No new compiler warnings introduced
45+
- [ ] CHANGELOG.md updated (for user-facing changes)

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737

3838
- name: Upload test reports and coverage (if present)
3939
if: always()
40-
uses: actions/upload-artifact@v4
40+
uses: actions/upload-artifact@v6
4141
with:
4242
name: reports-jdk-${{ matrix.java-version }}
4343
if-no-files-found: ignore
@@ -68,7 +68,7 @@ jobs:
6868

6969
- name: Upload IT reports and coverage
7070
if: always()
71-
uses: actions/upload-artifact@v4
71+
uses: actions/upload-artifact@v6
7272
with:
7373
name: reports-integration
7474
if-no-files-found: ignore

.github/workflows/qodana_code_quality.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
2121
fetch-depth: 0 # a full history is required for pull request analysis
2222
- name: 'Qodana Scan'
23-
uses: JetBrains/qodana-action@v2025.2
23+
uses: JetBrains/qodana-action@v2025.3
2424
with:
2525
pr-mode: false
2626
env:

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ jobs:
9191

9292
- name: Upload coverage reports
9393
if: always()
94-
uses: actions/upload-artifact@v4
94+
uses: actions/upload-artifact@v6
9595
with:
9696
name: reports-release
9797
if-no-files-found: ignore

AGENTS.md

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,106 @@ The URL format for the NIPs is https://github.com/nostr-protocol/nips/blob/maste
9898

9999

100100
## Coding
101-
- When writing code, follow the "Clean Code" principles:
102-
- [Clean Code](https://dev.398ja.xyz/books/Clean_Architecture.pdf)
103-
- Relevant chapters: 2, 3, 4, 7, 10, 17
104-
- [Clean Architecture](https://dev.398ja.xyz/books/Clean_Code.pdf)
105-
- Relevant chapters: All chapters in part III and IV, 7-14.
106-
- [Design Patterns](https://github.com/iluwatar/java-design-patterns)
107-
- Follow design patterns as described in the book, whenever possible.
108-
- When commiting code, follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.
109-
- When adding new features, ensure they are compliant with the Cashu specification (NUTs) provided above.
110-
- Make use of the lombok library to reduce boilerplate code.
101+
102+
When writing code, follow Clean Code and Clean Architecture principles:
103+
104+
### Meaningful Names
105+
- Use intention-revealing names that explain why something exists, what it does, and how it's used
106+
- Avoid disinformation: don't use names that could mislead (e.g., `accountList` for something that isn't a List)
107+
- Make meaningful distinctions: avoid noise words like `Info`, `Data`, `Manager` unless they add real meaning
108+
- Use pronounceable and searchable names; avoid single-letter variables except for loop counters
109+
- Class names should be nouns (`Customer`, `Account`); method names should be verbs (`postPayment`, `save`)
110+
- Pick one word per concept and stick with it (`fetch`, `retrieve`, `get` — pick one)
111+
112+
### Functions
113+
- Keep functions small: ideally under 20 lines, rarely exceeding one screen
114+
- Functions should do one thing, do it well, and do it only
115+
- One level of abstraction per function: don't mix high-level policy with low-level details
116+
- Use descriptive names: a long descriptive name is better than a short cryptic one
117+
- Minimize arguments: zero is ideal, one or two are fine, three requires justification
118+
- Avoid flag arguments (boolean parameters that change behavior)
119+
- Functions should either do something or answer something, never both (Command-Query Separation)
120+
- Prefer exceptions over error codes; extract try/catch blocks into their own functions
121+
122+
### Comments
123+
- Comments are a failure to express intent in code; prefer self-documenting code
124+
- Good comments: legal comments, explanation of intent, clarification, warning of consequences, TODO notes, Javadoc for public APIs
125+
- Bad comments: redundant comments, misleading comments, mandated comments, journal comments, noise comments, commented-out code
126+
- If you must comment, explain *why*, not *what* — the code shows what
127+
128+
### Error Handling
129+
- Use exceptions rather than return codes
130+
- Write try-catch-finally statements first when writing code that could throw
131+
- Use unchecked exceptions; checked exceptions violate the Open/Closed Principle
132+
- Provide context with exceptions: include operation attempted and failure type
133+
- Define exception classes by how they're caught, not by their source
134+
- Don't return null — throw an exception or return a Special Case object instead
135+
- Don't pass null as arguments unless the API explicitly expects it
136+
137+
### Classes
138+
- Classes should be small, measured by responsibilities (Single Responsibility Principle)
139+
- A class should have only one reason to change
140+
- High cohesion: methods and variables should be closely related
141+
- Organize for change: isolate code that's likely to change from code that's stable
142+
- Depend on abstractions, not concretions (Dependency Inversion)
143+
- Classes should be open for extension but closed for modification (Open/Closed Principle)
144+
145+
### Code Smells and Heuristics
146+
- Avoid comments that could be replaced by better naming or structure
147+
- Eliminate dead code, duplicate code, and code at wrong levels of abstraction
148+
- Keep configuration data at high levels; don't bury magic numbers
149+
- Follow the Law of Demeter: modules shouldn't know about the innards of objects they manipulate
150+
- Make logical dependencies physical: if one module depends on another, make that explicit
151+
- Prefer polymorphism to if/else or switch/case chains
152+
- Follow standard conventions for the project and language
153+
- Replace magic numbers with named constants
154+
- Be precise: don't be lazy about decisions — if you decide to use a list, be sure you need one
155+
- Encapsulate conditionals: extract complex boolean expressions into well-named methods
156+
- Avoid negative conditionals: `if (buffer.shouldCompact())` is clearer than `if (!buffer.shouldNotCompact())`
157+
- Functions should descend one level of abstraction
158+
159+
### SOLID Design Principles
160+
161+
**Single Responsibility Principle (SRP)**
162+
A module should have one, and only one, reason to change. Each class serves one actor or stakeholder. When requirements change for one actor, only the relevant module changes.
163+
164+
**Open/Closed Principle (OCP)**
165+
Software entities should be open for extension but closed for modification. Achieve this through abstraction and polymorphism — add new behavior by adding new code, not changing existing code.
166+
167+
**Liskov Substitution Principle (LSP)**
168+
Subtypes must be substitutable for their base types without altering program correctness. If S is a subtype of T, objects of type T may be replaced with objects of type S without breaking the program.
169+
170+
**Interface Segregation Principle (ISP)**
171+
Clients should not be forced to depend on interfaces they don't use. Prefer many small, client-specific interfaces over one general-purpose interface.
172+
173+
**Dependency Inversion Principle (DIP)**
174+
High-level modules should not depend on low-level modules; both should depend on abstractions. Abstractions should not depend on details; details should depend on abstractions.
175+
176+
### Component Principles
177+
178+
**Cohesion Principles:**
179+
- **REP (Reuse/Release Equivalence)**: The granule of reuse is the granule of release — classes in a component should be releasable together
180+
- **CCP (Common Closure)**: Gather classes that change for the same reasons at the same times; separate classes that change at different times for different reasons
181+
- **CRP (Common Reuse)**: Don't force users to depend on things they don't need — classes in a component should be used together
182+
183+
**Coupling Principles:**
184+
- **ADP (Acyclic Dependencies)**: No cycles in the component dependency graph; use Dependency Inversion to break cycles
185+
- **SDP (Stable Dependencies)**: Depend in the direction of stability — volatile components should depend on stable ones
186+
- **SAP (Stable Abstractions)**: Stable components should be abstract; instability should be concrete
187+
188+
### Design Patterns
189+
Apply established patterns where appropriate:
190+
- **Creational**: Factory Method, Abstract Factory, Builder, Singleton (use sparingly), Prototype
191+
- **Structural**: Adapter, Bridge, Composite, Decorator, Facade, Proxy
192+
- **Behavioral**: Strategy, Observer, Command, State, Template Method, Iterator, Chain of Responsibility
193+
194+
Choose patterns that simplify the design; don't force patterns where simpler solutions suffice.
195+
196+
### General Guidelines
197+
- When committing code, follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification
198+
- When adding new features, ensure they are compliant with the Nostr specification (NIPs) provided above
199+
- Make use of the Lombok library to reduce boilerplate code
200+
- Always rely on imports rather than fully qualified class names in code to keep implementations readable
111201

112202
## Documentation
113203

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,31 @@ The format is inspired by Keep a Changelog, and this project adheres to semantic
88

99
No unreleased changes yet.
1010

11+
## [1.2.1] - 2026-01-21
12+
13+
### Fixed
14+
- NIP-44 now correctly uses HKDF-Extract for conversation key derivation, ensuring proper cryptographic key generation.
15+
- WebSocket client now correctly accumulates all relay responses (EVENT messages) before completing, waiting for termination signals (EOSE, OK, NOTICE, CLOSED) instead of returning after the first message.
16+
- WebSocket client thread-safety improved by encapsulating pending request state, preventing potential race conditions when multiple threads call send() concurrently.
17+
- WebSocket client now rejects concurrent send() calls with IllegalStateException instead of silently orphaning the previous request's future.
18+
- KindFilter and ClassifiedListingEventDeserializer now use Kind.valueOfStrict() for fail-fast deserialization of unknown kind values.
19+
20+
### Changed
21+
- Kind.valueOf(int) now returns null for unknown kind values instead of throwing, allowing graceful handling of custom or future NIP kinds during JSON deserialization.
22+
- Added Kind.valueOfStrict(int) for callers who need fail-fast behavior on unknown kinds.
23+
- Added Kind.findByValue(int) returning Optional<Kind> for safe, explicit handling of unknown kinds.
24+
25+
## [1.2.0] - 2025-12-26
26+
27+
### Fixed
28+
- NIP-44 encryption now correctly uses HKDF instead of PBKDF2 for key derivation, as required by the specification. This fix enables DM interoperability between Java backend and JavaScript frontend implementations (e.g., nostr-tools).
29+
30+
### Changed
31+
- Switched integration tests to use strfry relay for improved robustness.
32+
33+
### Removed
34+
- Removed AGENTS.md and CLAUDE.md documentation files from the repository.
35+
1136
## [1.1.1] - 2025-12-24
1237

1338
### Fixed

nostr-java-api/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<groupId>xyz.tcheeric</groupId>
66
<artifactId>nostr-java</artifactId>
7-
<version>1.1.1</version>
7+
<version>1.2.1</version>
88
<relativePath>../pom.xml</relativePath>
99
</parent>
1010

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
##
2+
## strfry config for integration testing (no whitelist)
3+
##
4+
5+
db = "./strfry-db/"
6+
7+
dbParams {
8+
maxreaders = 256
9+
mapsize = 10995116277760
10+
noReadAhead = false
11+
}
12+
13+
events {
14+
maxEventSize = 65536
15+
rejectEventsNewerThanSeconds = 900
16+
rejectEventsOlderThanSeconds = 94608000
17+
rejectEphemeralEventsOlderThanSeconds = 60
18+
ephemeralEventsLifetimeSeconds = 300
19+
maxNumTags = 2000
20+
maxTagValSize = 1024
21+
}
22+
23+
relay {
24+
bind = "0.0.0.0"
25+
port = 7777
26+
nofiles = 1000000
27+
realIpHeader = ""
28+
29+
info {
30+
name = "nostr-java test relay"
31+
description = "strfry relay for nostr-java integration tests"
32+
pubkey = ""
33+
contact = ""
34+
icon = ""
35+
nips = ""
36+
}
37+
38+
maxWebsocketPayloadSize = 131072
39+
maxReqFilterSize = 200
40+
autoPingSeconds = 55
41+
enableTcpKeepalive = false
42+
queryTimesliceBudgetMicroseconds = 10000
43+
maxFilterLimit = 500
44+
maxSubsPerConnection = 20
45+
46+
writePolicy {
47+
# No write policy plugin - accept all events
48+
plugin = ""
49+
}
50+
51+
compression {
52+
enabled = true
53+
slidingWindow = true
54+
}
55+
56+
logging {
57+
dumpInAll = false
58+
dumpInEvents = false
59+
dumpInReqs = false
60+
dbScanPerf = false
61+
invalidEvents = true
62+
}
63+
64+
numThreads {
65+
ingester = 3
66+
reqWorker = 3
67+
reqMonitor = 3
68+
negentropy = 2
69+
}
70+
71+
negentropy {
72+
enabled = true
73+
maxSyncEvents = 1000000
74+
}
75+
}

nostr-java-base/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<groupId>xyz.tcheeric</groupId>
66
<artifactId>nostr-java</artifactId>
7-
<version>1.1.1</version>
7+
<version>1.2.1</version>
88
<relativePath>../pom.xml</relativePath>
99
</parent>
1010

0 commit comments

Comments
 (0)