# Release Notes: v1.4.0

**Release Date:** November 3, 2025

## Overview

Version 1.4.0 enhances the Filter validation system to accept zero as a valid value for `since`, `until`, and `limit` fields, improving protocol compliance and flexibility.

## What's Changed

### Filter Validation Enhancement

Previously, the Filter class required `since`, `until`, and `limit` fields to be strictly positive integers (> 0). This release updates the validation to accept non-negative integers (>= 0), allowing zero as a valid value.

#### Key Changes

- **`since=0`**: Now valid - represents Unix epoch start (January 1, 1970, 00:00:00 UTC)
- **`until=0`**: Now valid - represents Unix epoch start (edge case but technically valid)
- **`limit=0`**: Now valid - represents a request for zero results (unusual but valid use case)

#### Before (v1.3.0)

```python
from nostr_tools import Filter, FilterValidationError

# These would raise FilterValidationError
filter1 = Filter(since=0)  # ❌ Error: must be a positive integer
filter2 = Filter(until=0)  # ❌ Error: must be a positive integer
filter3 = Filter(limit=0)  # ❌ Error: must be a positive integer
```

#### After (v1.4.0)

```python
from nostr_tools import Filter

# These are now valid
filter1 = Filter(since=0)  # ✅ Valid: Unix epoch start
filter2 = Filter(until=0)  # ✅ Valid: Unix epoch start
filter3 = Filter(limit=0)  # ✅ Valid: No results requested

assert filter1.is_valid  # True
assert filter2.is_valid  # True
assert filter3.is_valid  # True
```

### Error Message Updates

Validation error messages have been updated to reflect the new constraint:

- **Before**: `"must be a positive integer"`
- **After**: `"must be a non-negative integer"`

```python
from nostr_tools import Filter, FilterValidationError

try:
    filter = Filter(since=-1)  # Still invalid
except FilterValidationError as e:
    print(e)  # "since must be a non-negative integer"
```

## Migration Guide

### From v1.3.0 to v1.4.0

This is a **non-breaking change**. All code that worked in v1.3.0 will continue to work in v1.4.0.

#### No Changes Required

If you're not using zero values for filter fields, no changes are needed:

```python
# This code works in both v1.3.0 and v1.4.0
filter = Filter(kinds=[1], since=1000000, limit=10)
```

#### New Functionality Available

You can now use zero values if needed:

```python
# New in v1.4.0: Zero values are accepted
filter = Filter(
    kinds=[1],
    since=0,        # Get events from epoch start
    until=int(time.time()),
    limit=0         # Request zero results (for testing)
)
```

#### Error Handling Updates (Optional)

If your code catches and parses `FilterValidationError` messages, you may want to update the expected error text:

```python
# Optional: Update error message checks
try:
    filter = Filter(since=-1)
except FilterValidationError as e:
    # v1.3.0: "must be a positive integer"
    # v1.4.0: "must be a non-negative integer"
    assert "non-negative" in str(e)
```

## Technical Details

### Modified Files

1. **filter.py** (`src/nostr_tools/core/filter.py`)
   - Updated validation logic (line 260): Changed constraint from `<= 0` to `< 0`
   - Updated field docstrings (lines 82-87): Added `>= 0` constraint documentation
   - Updated method parameter documentation (lines 112-114): Reflected `>= 0` constraint

2. **test_filter.py** (`tests/unit/test_filter.py`)
   - Added 3 new positive tests for zero values
   - Updated 3 existing negative tests for error message changes
   - Total: 541 tests (3 new tests added)

3. **errors.py** (`src/nostr_tools/exceptions/errors.py`)
   - Updated `FilterValidationError` docstring example (line 150)

### Code Changes Summary

**Lines Changed**: +21/-11
- 11 lines removed (old validation logic and error messages)
- 21 lines added (new validation logic, updated tests, and documentation)

### Test Coverage

- **Total Tests**: 541 (3 new)
- **Coverage**: 80%+ maintained
- **Type Checking**: All MyPy checks pass
- **Code Quality**: All Ruff checks pass
- **Security**: All security scans pass (Bandit, Safety, pip-audit)

## Compatibility

### Python Versions

Supports Python 3.9, 3.10, 3.11, 3.12, and 3.13.

### Dependencies

No dependency changes in this release.

### Breaking Changes

**None**. This release is fully backward compatible with v1.3.0.

## Upgrade Instructions

### Using pip

```bash
pip install --upgrade nostr-tools==1.4.0
```

### Using poetry

```bash
poetry add nostr-tools@^1.4.0
```

### Verify Installation

```python
import nostr_tools
print(nostr_tools.__version__)  # Should print: 1.4.0
```

## Examples

### Use Case 1: Get All Events Since Unix Epoch

```python
from nostr_tools import Filter

# Get all text notes since the beginning of Unix time
filter = Filter(
    kinds=[1],      # Text notes
    since=0,        # From Unix epoch start
    limit=100       # Limit results
)
```

### Use Case 2: Time Range Including Epoch

```python
import time

# Get events in a time range that includes epoch
filter = Filter(
    kinds=[1],
    since=0,                    # From epoch start
    until=int(time.time()),     # Until now
    limit=50
)
```

### Use Case 3: Testing with Zero Limit

```python
# Useful for testing relay connectivity without retrieving data
filter = Filter(
    kinds=[1],
    limit=0  # Request zero results (relay will return EOSE immediately)
)
```

## Known Issues

None.

## Support

### Supported Versions

| Version | Support Status | End of Support |
|---------|----------------|----------------|
| 1.4.0   | ✅ Active      | TBD            |
| 1.3.0   | ❌ EOL         | 2025-11-03     |
| ≤ 1.2.1 | ❌ EOL         | Earlier        |

### Getting Help

- **Documentation**: [https://bigbrotr.github.io/nostr-tools/](https://bigbrotr.github.io/nostr-tools/)
- **Issues**: [https://github.com/bigbrotr/nostr-tools/issues](https://github.com/bigbrotr/nostr-tools/issues)
- **PyPI**: [https://pypi.org/project/nostr-tools/](https://pypi.org/project/nostr-tools/)

## What's Next

### Upcoming in Future Releases

- Enhanced NIP support
- Performance optimizations
- Additional relay capabilities

Stay tuned for more updates!

## Contributors

This release was made possible by the nostr-tools development team.

## Changelog

For a complete list of changes, see [CHANGELOG.md](../CHANGELOG.md).

---

**Full Changelog**: v1.3.0...v1.4.0
